File management
Pruvious allows you to effortlessly upload files either in a local directory within your project or on a remote S3 server.
Example
Here's an example of how to upload an image from the client to the server using a custom component and API route:
# components/UploadAvatar.vue
<template>
<div>
<form @submit.prevent="submit">
<input name="$file" type="file" />
<button type="submit">Upload</button>
</form>
<p v-if="error" class="text-red-500">{{ error }}</p>
<img v-if="imageSrc" :src="imageSrc" />
</div>
</template>
<script lang="ts" setup>
import { isString } from '#pruvious'
const error = ref('')
const imageSrc = ref('')
async function submit(event: Event) {
error.value = ''
await $fetch<string>('/api/avatar', {
method: 'post',
body: new FormData(event.target as HTMLFormElement),
})
.then((res) => {
imageSrc.value = res
})
.catch(({ data }) => {
error.value = isString(data) ? data : JSON.stringify(data)
})
}
</script>
Now, let's create a server handler that will store the image in the database and a storage drive.
# server/api/avatar.post.ts
import { getPublicFilePath, imageTypes, isFile } from '#pruvious'
import { query, readInputData } from '#pruvious/server'
export default defineEventHandler(async (event) => {
const input = await readInputData(event, 'uploads')
if (input.errors.length) {
setResponseStatus(event, 400)
return input.errors.join('\n')
}
if (Array.isArray(input.data)) {
setResponseStatus(event, 400)
return 'You can only upload one file at a time'
} else if (isFile(input.data.$file) && !imageTypes.includes(input.data.$file.type)) {
setResponseStatus(event, 422)
return { $file: 'The file must be an image' }
}
const result = await query('uploads').create({
$file: input.data.$file!,
directory: 'avatars',
})
if (result.success) {
return getPublicFilePath(result.record, useRuntimeConfig())
} else if (result.message) {
setResponseStatus(event, 400)
return result.message
} else {
setResponseStatus(event, 422)
return result.errors
}
})
Pruvious uses a special $file
field to associate a File
with an uploads
record. This field is only accessible during record creation. Once a $file
is linked to an uploads
record, it cannot be modified. To make changes, you need to create a new record and delete the old one.
Image optimization
Pruvious uses the sharp library to manipulate images in real-time. When working with image fields, the images are automatically optimized according to the specified sources
option. If you wish to manually transform an image, you can use the getOptimizedImage
function.
In the following example, we convert the uploaded image to webp and include the absolute path (for local storage drive) or URL (for S3 drive) of the optimized image in the response.
# server/api/avatar.post.ts
import { imageTypes, isFile } from '#pruvious'
import { getOptimizedImage, query, readInputData } from '#pruvious/server'
export default defineEventHandler(async (event) => {
const input = await readInputData(event, 'uploads')
if (input.errors.length) {
setResponseStatus(event, 400)
return input.errors.join('\n')
}
if (Array.isArray(input.data)) {
setResponseStatus(event, 400)
return 'You can only upload one file at a time'
} else if (isFile(input.data.$file) && !imageTypes.includes(input.data.$file.type)) {
setResponseStatus(event, 422)
return { $file: 'The file must be an image' }
}
const result = await query('uploads').create({
$file: input.data.$file!,
directory: 'avatars',
})
if (result.success) {
const webp = await getOptimizedImage(result.record, { format: 'webp' })
if (webp.success) {
return webp.src
} else {
setResponseStatus(event, 400)
return webp.error
}
} else if (result.message) {
setResponseStatus(event, 400)
return result.message
} else {
setResponseStatus(event, 422)
return result.errors
}
})
When the original upload record is deleted, all optimized images are also removed.
Local storage
The local storage is the default storage drive. It stores all uploaded files in the .uploads
directory in your project's root. You can customize the default options in your nuxt.config.ts
file.
# nuxt.config.ts
export default defineNuxtConfig({
modules: ['pruvious'],
pruvious: {
uploads: {
drive: {
type: 'local',
path: './.uploads',
urlPrefix: 'uploads',
},
},
},
})
S3 storage
The S3 drive utilizes Amazon S3 cloud storage for file reading and writing. You can configure it in your nuxt.config.ts
file as follows:
# nuxt.config.ts
export default defineNuxtConfig({
modules: ['pruvious'],
pruvious: {
uploads: {
drive: {
type: 's3',
baseUrl: 'https://your-space-here.fra1.digitaloceanspaces.com',
bucket: 'your-space-here',
endpoint: 'fra1.digitaloceanspaces.com',
key: 'access-key',
region: 'fra1',
secret: 'secret-key',
}
},
},
})
Maximum upload size
You can set the maximum upload size in your nuxt.config.ts
file. Here's an example:
# nuxt.config.ts
export default defineNuxtConfig({
modules: ['pruvious'],
pruvious: {
uploads: {
maxFileSize: '16 MB',
},
},
})
Last updated on March 18, 2024 at 17:58