Vue
Reactive upload state for Vue 3. Same upload flow as browser uploads, wrapped in a composable plus a headless component.
useUpload
Import from sonuslab-storage/vue. Returns reactive status, progress, and error refs plus upload() and reset() methods.
Uploader.vue
<script setup lang="ts">
import { useUpload } from 'sonuslab-storage/vue'
const { upload, status, progress, error, reset } = useUpload({
presignEndpoint: '/api/upload/presign',
completeEndpoint: '/api/upload/complete',
})
function onChange(e: Event) {
const file = (e.target as HTMLInputElement).files?.[0]
if (file) upload(file)
}
</script>
<template>
<input type="file" @change="onChange" :disabled="status === 'uploading'" />
<p v-if="status === 'uploading'">{{ progress?.percent ?? 0 }}%</p>
<template v-if="status === 'error'">
<p>{{ error?.message }}</p>
<button @click="reset">Retry</button>
</template>
</template>Reactive refs
| Parameter | Type | Description |
|---|---|---|
status | Ref<'idle' | 'uploading' | 'complete' | 'error'> | Current upload state. |
progress | Ref<{ loaded, total, percent } | null> | Live progress during the PUT (0–100). |
error | Ref<Error | null> | Populated when status is error. |
result | Ref<UploadResult | null> | fileId + key after status becomes complete. |
Methods
| Parameter | Type | Description |
|---|---|---|
upload(file) | (file: File | Blob) => Promise<UploadResult> | Run the presign → PUT → complete flow. |
reset() | () => void | Clear status, progress, error, and result back to idle. |
cancel() | () => void | Abort the in-flight upload. |
Lifecycle callbacks
Pass these in useUpload({ ... }) for side-effects without watching status.
| Parameter | Type | Description |
|---|---|---|
onStart | (file: File) => void | Fires when upload() is invoked, before any network I/O. |
onComplete | (result: UploadResult) => void | Fires after the complete step resolves. |
onError | (err: Error) => void | Fires when the upload rejects (after status becomes error). |
<StorageUpload>
A headless component wrapping useUpload. The default slot receives status, progress, trigger, and inputProps — bring your own markup.
AvatarUpload.vue
<script setup lang="ts">
import { StorageUpload } from 'sonuslab-storage/vue'
</script>
<template>
<StorageUpload
presign-endpoint="/api/upload/presign"
complete-endpoint="/api/upload/complete"
accept="image/*"
:max-size="10_000_000"
@complete="(r) => console.log(r.fileId)"
>
<template #default="{ status, progress, trigger, inputProps }">
<button :disabled="status === 'uploading'" @click="trigger">
{{ status === 'uploading' ? `Uploading ${progress?.percent ?? 0}%` : 'Upload' }}
</button>
<input v-bind="inputProps" />
</template>
</StorageUpload>
</template>Props
| Parameter | Type | Description |
|---|---|---|
presign-endpointrequired | string | URL of the presign route on your server. |
complete-endpointrequired | string | URL of the complete route on your server. |
accept | string | Standard accept attribute (e.g. image/*). |
multiple | boolean | Allow multiple files. |
max-size | number | Client-side size check, in bytes. |
Events
| Parameter | Type | Description |
|---|---|---|
complete | (result: { fileId, key }) => void | Emitted when an upload finalizes successfully. |
error | (err: Error) => void | Emitted on any failure. |
progress | (p: { loaded, total, percent }) => void | Emitted during the PUT. |