Multiple file uploads

Hello all, I am struggling with the file upload to the python-backed webserver. I did not find any answers to the problem at hand with Nuxt, so I am asking here. I have taken the inspiration from the documentation, alas it doesn't work as intended. The problem is that the server receives the request with the form data containing only the file name but not the file contents (responds with HTTP 422). I am kinda struggling to pass around the file contents from the FormSubmitEvent to the API call. Help would be appreciated.
<template>
<div class="container mx-auto">
<h1>Upload files</h1>
<UForm :state="state" @submit="onSubmit">
<UFormField>
<UInput v-model="state.files" required id="uploader" accept=".pdf" multiple="multiple" type="file" />
</UFormField>

<UButton type="submit" >
Submit
</UButton>
</UForm>

<div class="pt-3">
<h2>Uploaded files</h2>
</div>
</div>
</template>

<script setup lang="ts">
import type { FormSubmitEvent } from '@nuxt/ui'
import * as v from 'valibot'

const schema = v.object({
files: v.array(v.string())
})

type Schema = v.InferOutput<typeof schema>

const state = reactive({
files: null,
})

function onSubmit(event: FormSubmitEvent<Schema>) {
console.log("data:", event.data)

fetch("http://localhost:8000/upload", {
method: "POST",
headers: {
Accept: "application/json",
},
body: /* ? */,
}).then((res) => {
console.log("upload: ", res)
})
}
</script>
<template>
<div class="container mx-auto">
<h1>Upload files</h1>
<UForm :state="state" @submit="onSubmit">
<UFormField>
<UInput v-model="state.files" required id="uploader" accept=".pdf" multiple="multiple" type="file" />
</UFormField>

<UButton type="submit" >
Submit
</UButton>
</UForm>

<div class="pt-3">
<h2>Uploaded files</h2>
</div>
</div>
</template>

<script setup lang="ts">
import type { FormSubmitEvent } from '@nuxt/ui'
import * as v from 'valibot'

const schema = v.object({
files: v.array(v.string())
})

type Schema = v.InferOutput<typeof schema>

const state = reactive({
files: null,
})

function onSubmit(event: FormSubmitEvent<Schema>) {
console.log("data:", event.data)

fetch("http://localhost:8000/upload", {
method: "POST",
headers: {
Accept: "application/json",
},
body: /* ? */,
}).then((res) => {
console.log("upload: ", res)
})
}
</script>
3 Replies
kapa.ai
kapa.ai19h ago
Hi @ShadowCaster. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To handle multiple file uploads in Nuxt with a Python backend, you need to ensure that the file input provides the actual file objects (not just file names) and that you send them as FormData in your API call. The code you provided uses <UInput type="file" /> from Nuxt UI, but by default, v-model on a file input will not give you the file objects directly—it will give you the file names or an empty string, which is why your backend only receives the file names and not the file contents. Key points: - You need to access the actual files from the input element. - You must construct a FormData object and append the files to it before sending the request. The Nuxt UI documentation and examples do not provide a direct example for file uploads, but based on the standard approach and the way Nuxt UI's UInput works, you should use a ref to access the files from the input element, then build your FormData in the submit handler. Here’s how you can adjust your code:
<template>
<div class="container mx-auto">
<h1>Upload files</h1>
<UForm :state="state" @submit="onSubmit">
<UFormField>
<UInput
ref="fileInput"
required
id="uploader"
accept=".pdf"
multiple
type="file"
/>
</UFormField>

<UButton type="submit">
Submit
</UButton>
</UForm>

<div class="pt-3">
<h2>Uploaded files</h2>
</div>
</div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const fileInput = ref<HTMLInputElement | null>(null)
const state = reactive({})

async function onSubmit() {
const files = fileInput.value?.input?.files
if (!files || files.length === 0) return

const formData = new FormData()
for (let i = 0; i < files.length; i++) {
formData.append('files', files[i])
}
const res = await fetch("<http://localhost:8000/upload",> {
method: "POST",
body: formData,
})
console.log("upload: ", res)
}
</script>
<template>
<div class="container mx-auto">
<h1>Upload files</h1>
<UForm :state="state" @submit="onSubmit">
<UFormField>
<UInput
ref="fileInput"
required
id="uploader"
accept=".pdf"
multiple
type="file"
/>
</UFormField>

<UButton type="submit">
Submit
</UButton>
</UForm>

<div class="pt-3">
<h2>Uploaded files</h2>
</div>
</div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const fileInput = ref<HTMLInputElement | null>(null)
const state = reactive({})

async function onSubmit() {
const files = fileInput.value?.input?.files
if (!files || files.length === 0) return

const formData = new FormData()
for (let i = 0; i < files.length; i++) {
formData.append('files', files[i])
}
const res = await fetch("<http://localhost:8000/upload",> {
method: "POST",
body: formData,
})
console.log("upload: ", res)
}
</script>
Notes: - The ref="fileInput" and accessing fileInput.value?.input?.files is necessary because UInput wraps the native input. You may need to adjust this depending on the actual DOM structure of UInput. - You do not need to set the Content-Type header when sending FormData; the browser will set it automatically. - The backend should expect files under the key 'files'. The knowledge sources do not provide a direct example for file uploads with Nuxt UI, but this approach follows standard file upload practices in Vue and Nuxt. If you need to integrate with Nuxt UI's form validation, you may need to handle file validation separately, as most schema validators expect strings, not File objects. For more on form handling, see the Nuxt UI Form documentation. If you need more details on integrating custom inputs with forms, see the useFormField composable. I'm sorry, but the knowledge sources do not contain a direct, working example of multiple file uploads with Nuxt UI. The above solution is based on standard practices and the available documentation. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai19h ago
<@295226139654488065> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
ShadowCaster
ShadowCasterOP15h ago
huh, I will try this approach! Doesn't fit the documentation.

Did you find this page helpful?