File Uploads¶
Upload files with Inertia form helpers and Litestar endpoints.
See also
Official Inertia.js docs: File Uploads
How File Uploads Work¶
Inertia will automatically submit FormData when a file is present. You can
also force FormData with forceFormData for mixed payloads.
Frontend Usage¶
import { useForm } from "@inertiajs/react";
export default function AvatarForm() {
const form = useForm({
name: "",
avatar: null as File | null,
});
function submit(e: React.FormEvent) {
e.preventDefault();
form.post("/profile", { forceFormData: true });
}
return (
<form onSubmit={submit}>
<input
type="file"
onChange={(e) => form.setData("avatar", e.target.files?.[0] ?? null)}
/>
<button disabled={form.processing}>Upload</button>
</form>
);
}
<script setup lang="ts">
import { useForm } from "@inertiajs/vue3";
const form = useForm({
name: "",
avatar: null as File | null,
});
function submit() {
form.post("/profile", { forceFormData: true });
}
</script>
<template>
<form @submit.prevent="submit">
<input type="file" @change="(e) => (form.avatar = e.target.files?.[0] ?? null)" />
<button :disabled="form.processing">Upload</button>
</form>
</template>
Upload Progress¶
Track progress using the progress field:
{form.progress && <progress value={form.progress.percentage} max="100" />}
<template>
<progress v-if="form.progress" :value="form.progress.percentage" max="100" />
</template>
Image Previews¶
Use URL.createObjectURL to preview images before upload:
const previewUrl = form.data.avatar
? URL.createObjectURL(form.data.avatar)
: null;
{previewUrl && <img src={previewUrl} alt="Preview" />}
<script setup lang="ts">
import { computed } from "vue";
const previewUrl = computed(() =>
form.avatar ? URL.createObjectURL(form.avatar) : null
);
</script>
<template>
<img v-if="previewUrl" :src="previewUrl" alt="Preview" />
</template>
Backend Usage¶
Handle files using Litestar’s UploadFile:
from litestar import post
from litestar.datastructures import UploadFile
from litestar.request import Request
from litestar_vite.inertia import InertiaRedirect
@post("/profile")
async def update_profile(
request: Request,
avatar: UploadFile | None = None,
) -> InertiaRedirect:
if avatar is not None:
await avatar.save("./uploads/avatar.png")
return InertiaRedirect(request, "/profile")
Multiple Files¶
@post("/documents")
async def upload_documents(request: Request, files: list[UploadFile]) -> InertiaRedirect:
for file in files:
await file.save(f"./uploads/{file.filename}")
return InertiaRedirect(request, "/documents")
See Also¶
Forms - Form submissions
Validation - Validation errors for uploads
Flash Data - Success messaging