Svelte上传图片至FastAPI后端持续返回422错误求助
图片上传时持续返回422 Unprocessable Entity错误排查
我尝试将图片上传至后端服务器时,持续收到INFO: 127.0.0.1:52154 - "POST /api/v1/contents/ HTTP/1.1" 422 Unprocessable Entity错误。最初使用Django REST Framework时就出现错误,以为是框架问题,换成FastAPI后仍遇到类似问题,推测可能与Svelte相关,但无法定位原因。我已添加如下请求头,错误依旧:
headers: { 'Content-Type': 'multipart/form-data', },
前端Svelte代码
<script lang="ts"> import { fly } from 'svelte/transition'; import type { SubmitFunction } from '@sveltejs/kit'; import { addAlert } from '$lib/store/store'; import { enhance } from '$app/forms'; import type { Post } from '$lib/types'; export let showPostModal: boolean; export let categories: any[]; export let post: Post | null = null; export let actions: string; let errors: any = {}; let loading: boolean = false; const dispatch = createEventDispatcher(); const closeModal = () => { dispatch('close'); }; const submit: SubmitFunction = ({ formData }) => { loading = true; return async ({ result, update }) => { try { if (result.status === 200) { console.log("200 status...........", result); dispatch('postCreated', result.data.newPost); addAlert({ message: `${post ? 'Post edited successfully' : 'New post created successfully'}`, type: 'success' }); closeModal(); } else if (result.status === 400) { console.log("400 error...........", result); errors = result?.data.errors; } else if (result.status === 500) { console.log("500 error..............", result); addAlert({ message: `${result.data.message}`, type: 'error' }); } } finally { loading = false; update(); } }; }; onMount(() => { categories = categories.map((category: any) => ({ label: category.name, value: category.uuid })); }); let photo: any[]; let category: string = post ? post.category_name : ''; let description: string = post ? post.description : ''; let title: string = post ? post.title : ''; $: author_name = post ? post.author_name : $currentUser?.name; console.log("author name...", currentUser.name, author_name); </script> {#if showPostModal} <div class="fixed inset-0 flex items-center justify-center z-50 left-0 transition-transform duration-300" in:fly={{ y: -100 }} out:fly={{ y: -100 }} class:slide-transition={{ showPostModal }} > <div on:click={closeModal} on:keydown={closeModal} class="w-full cursor-pointer h-full absolute bg-black opacity-30" /> <div on:keydown={closeModal} class="absolute w-8 z-[100] h-8 items-center flex justify-center cursor-pointer bg-white rounded-full font-bold top-3 right-3 text-3xl text-rose-600" on:click={closeModal} > <iconify-icon icon="material-symbols:cancel" /> </div> <div class="relative transform overflow-hidden rounded-lg bg-white text-left shadow-xl transition-all sm:my-8 mx-auto sm:max-w-xl md:max-w-[80rem]" > <form method="post" use:enhance={submit} enctype="multipart/form-data" action={actions} class="p-4 text-center flex h-[500px] flex-col gap-5 overflow-y-auto" > <h1 class="mb-1 text-xl font-bold">{post ? 'Edit Post' : 'Create Post'}</h1> <input type="file" name="photo" accept="image/*"/> <div class="mt-5 flex justify-center w-full"> <button type="submit" class="py-2.5 outline-none px-4 inline-flex justify-center items-center gap-2 rounded-md border border-transparent font-semibold bg-primary text-white hover:bg-blue-900 w-full focus:ring-offset-2 transition-all text-sm" > {#if loading} <iconify-icon icon="line-md:loading-loop" width="20" />{:else} {post ? 'Edit Post' : 'Create Post'} {/if} </button> </div> </form> </div> </div> {/if} </script>
后端FastAPI代码
from fastapi import File, UploadFile, HTTPException, status @router.post("/contents/") async def create_content(photo: UploadFile = File(..., max_length=10*1024*1024)): print(photo, photo.filename, photo.content_type)
错误原因分析及解决方案
核心原因
手动设置Content-Type: multipart/form-data是关键问题。浏览器在处理文件上传时,会自动生成包含boundary(分隔符)的完整Content-Type头(例如multipart/form-data; boundary=----WebKitFormBoundaryxxxx),手动固定头会丢失boundary,导致后端无法正确解析表单数据,直接触发422错误。
具体解决步骤
移除手动设置的Content-Type头
删除你添加的手动设置请求头的代码,让浏览器自动生成符合规范的请求头。验证表单数据是否正确携带文件
在submit函数中添加日志,确认文件被正确加入FormData:const submit: SubmitFunction = ({ formData }) => { console.log('表单中的文件:', formData.get('photo')); // 检查是否有File对象输出 loading = true; // 原有逻辑不变 };如果没有输出文件对象,检查input元素是否正常渲染,或是否有其他JS代码干扰表单数据。
后端增加错误日志定位细节
修改后端代码,返回具体错误信息,方便排查:from fastapi import File, UploadFile, status from fastapi.responses import JSONResponse @router.post("/contents/") async def create_content(photo: UploadFile = File(..., max_length=10*1024*1024)): try: print(photo, photo.filename, photo.content_type) return {"message": "上传成功"} except Exception as e: return JSONResponse( status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, content={"detail": str(e)} )用浏览器工具检查请求
打开开发者工具的Network面板,查看POST请求的Form Data部分,确认photo字段存在且包含文件数据。
内容的提问来源于stack exchange,提问作者Tim
相关产品推荐
相关产品推荐

