You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SvelteKit大文件上传报错:Failed to parse body as FormData

问题

我正在用SvelteKit开发Google相册导出文件(含图片的大型Zip文件)上传功能,前端代码如下:

console.log(`uploading google archive file ${i}/${files.length}`);
const file = files[i];
const xhr = new XMLHttpRequest();
xhr.open('POST', '/api/google-import');
xhr.onload = () => {
    if (xhr.status >= 200 && xhr.status < 300) {
        resolve();
    } else {
        reject(new Error(`Archive upload failed with status ${xhr.status}.`));
    }
};
xhr.onerror = () => {
    reject(new Error('Archive upload failed due to a network error.'));
};
const formData = new FormData();
formData.append('file', file);
xhr.send(formData);

小型JPG上传正常,但上传10GB级别的Zip文件时触发500错误,后端简化代码如下:

export const POST: RequestHandler = async ({ request }) => {
    const formData = await request.formData();
    return new Response('', { status: 200 });
};

报错信息:

[500] POST /api/google-import
TypeError: Failed to parse body as FormData.
    at parsingError (node:internal/deps/undici/undici:6114:14)

已设置环境变量BODY_SIZE_LIMIT为60G,但问题仍未解决,请问遗漏了什么配置?


解决方案

1. 改用流式处理替代内存加载

直接调用request.formData()会将整个大文件加载到内存,这是解析失败的核心原因。改用流式处理,借助busboy库分块读取文件:

import type { RequestHandler } from '@sveltejs/kit';
import busboy from 'busboy';

export const POST: RequestHandler = async ({ request }) => {
    const contentType = request.headers.get('content-type');
    if (!contentType?.includes('multipart/form-data')) {
        return new Response('Invalid content type', { status: 400 });
    }

    const bb = busboy({ headers: Object.fromEntries(request.headers.entries()) });

    return new Response(async () => {
        return new ReadableStream({
            start(controller) {
                bb.on('file', (_name, file) => {
                    file.on('data', chunk => controller.enqueue(chunk));
                    file.on('end', () => controller.close());
                    file.on('error', err => controller.error(err));
                });

                bb.on('error', err => controller.error(err));

                // 将请求体流导入busboy
                request.body?.pipeTo(new WritableStream({
                    write(chunk) { bb.write(chunk); },
                    close() { bb.end(); }
                })).catch(err => controller.error(err));
            }
        });
    }, { status: 200 });
};

这种方式不会将整个文件存入内存,从根源避免解析失败。

2. 检查Undici的深层配置

SvelteKit依赖Undici处理HTTP请求,除了BODY_SIZE_LIMIT,还需确保Undici的maxBodySize和超时配置足够。可以在hooks.server.ts中针对特定请求调整:

import type { Handle } from '@sveltejs/kit';

export const handle: Handle = async ({ event, resolve }) => {
    if (event.request.url.includes('/api/google-import') && event.request.method === 'POST') {
        // 重写formData方法,避免内置解析的内存限制
        const originalFormData = event.request.formData;
        event.request.formData = async () => {
            // 这里可以用第三方库手动解析multipart流,或者直接处理原始流
            const body = await event.request.arrayBuffer();
            // 示例:返回空FormData(实际需根据业务处理)
            return new FormData();
        };
    }
    return resolve(event);
};

3. 排查部署平台限制

如果部署在Vercel、Netlify等平台,平台自身可能有请求体大小限制:

  • Vercel Serverless函数默认最大请求体4.5GB,需改用Edge函数或配置Blob存储中转
  • Netlify函数默认限制10MB,需调整为大文件上传方案(如直接上传到对象存储)

如果是自部署Node.js服务器,需检查适配器的配置,比如使用@sveltejs/adapter-node时,在server.js中添加:

import express from 'express';
import { handler } from './build/handler.js';
import multer from 'multer';

const app = express();
// 配置multer处理大文件上传
const upload = multer({ 
    dest: 'uploads/', 
    limits: { fileSize: 60 * 1024 * 1024 * 1024 } // 60GB限制
});

// 优先用multer处理上传请求
app.post('/api/google-import', upload.single('file'), (req, res) => {
    // 处理上传后的文件
    res.sendStatus(200);
});

app.use(handler);
app.listen(3000);

4. 前端优化上传配置

大文件上传易超时,前端需添加超时处理和进度监听:

xhr.timeout = 3600000; // 设置1小时超时
xhr.ontimeout = () => reject(new Error('Upload timed out'));

// 添加上传进度监听
xhr.upload.onprogress = (e) => {
    if (e.lengthComputable) {
        const progress = (e.loaded / e.total) * 100;
        console.log(`Upload progress: ${progress.toFixed(2)}%`);
    }
};

内容的提问来源于stack exchange,提问作者munHunger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 20:13:10