使用Fetch上传文件至Express服务器,Multer报Unexpected end of form错误
问题:Fetch上传文件配合Express+Multer失败的有效解决办法
此前已有用户提出过该问题,给出的解决方案为使用body-parser并将Multer降级至1.4.3,但这并非根本解决办法。我尝试使用Fetch上传文件,手动设置了boundary(不设置则会报错,但该boundary是从网上随意获取的,怀疑这可能是错误原因),目前请求失败,寻求有效解决方法。
前端代码
const file = fs.createReadStream(`${desktopDir}/ai2html-output/home-pro-Artboard_1.jpg`); const title = "Test"; const form = new FormData(); form.append("title", title); form.append("file", file); const response = await fetch('https://example.com/uploads/1234', { method: 'POST', headers: { "Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryyEmKNDsBKjB7QEqu", }, body: form }); const responseData = await response.json();
注:手动设置boundary是因为不设置会报错,但该boundary为网上随意获取。
服务器端Express配置
const multer = require('multer'); const upload = multer({ dest: '/var/www/vhosts/preview.inkto.art/httpdocs/html/' }); router.post('/uploads/:id', upload.single('file'), function(req, res) { const title = req.body.title; res.json({ msg: `file ${title} uploaded successfully!` }); });
服务器收到的请求头信息
:method: POST :path: /uploads/1234 :scheme: https accept: */* accept-encoding: gzip, deflate, br accept-language: en-US,en;q=0.9 content-length: 17 content-type: multipart/form-data; boundary=----WebKitFormBoundaryyEmKNDsBKjB7QEqu origin: file:// sec-fetch-dest: empty sec-fetch-mode: cors sec-fetch-site: cross-site user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 12_4_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36
解决办法
1. 移除手动设置的Content-Type头
当使用FormData作为fetch的body时,浏览器会自动生成包含正确boundary的Content-Type头。手动设置的boundary和FormData内部实际使用的不一致,会导致服务器无法解析表单数据,这是核心问题。
修改后的前端代码:
const file = fs.createReadStream(`${desktopDir}/ai2html-output/home-pro-Artboard_1.jpg`); const title = "Test"; const form = new FormData(); form.append("title", title); form.append("file", file); const response = await fetch('https://example.com/uploads/1234', { method: 'POST', // 移除手动设置的Content-Type,让浏览器自动生成 body: form }); const responseData = await response.json();
2. 配置服务器CORS规则
请求origin为file://,属于跨域请求,需确保Express服务器允许该来源的请求,或至少允许OPTIONS预检请求通过。可以使用cors中间件:
const cors = require('cors'); // 允许file://来源的请求 app.use(cors({ origin: 'file://' })); // 开发环境可临时允许所有来源 // app.use(cors());
3. 检查文件流的有效性
确保文件路径正确、文件存在且有读取权限,可添加错误处理:
const fileStream = fs.createReadStream(`${desktopDir}/ai2html-output/home-pro-Artboard_1.jpg`); fileStream.on('error', (err) => { console.error('读取文件失败:', err); }); form.append("file", fileStream);
4. 完善Multer配置与错误捕获
确认Multer的dest目录存在且服务器有写入权限,同时添加错误捕获中间件:
router.post('/uploads/:id', upload.single('file'), function(req, res) { const title = req.body.title; res.json({ msg: `file ${title} uploaded successfully!` }); }, (err, req, res, next) => { // 捕获Multer上传错误 res.status(400).json({ error: err.message }); });
内容的提问来源于stack exchange,提问作者FabricioG
相关产品推荐
相关产品推荐

