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

JS fetch的FormData中基于Blob创建zip文件上传报400错误

问题说明

在JavaScript中使用fetch搭配FormData上传zip文件时,通过<input type="file">控件读取的本地zip文件可正常上传,但自行通过Blob生成的shapefile格式zip文件上传时始终返回400 Bad Request错误。

可正常运行的文件选择上传代码

// 本地文件选择上传逻辑
var fileInput = document.getElementById('avatar');   
var filename = fileInput.files[0].name;

var headers = new Headers();
headers.set('X-CSRFToken', csrftoken);
var formData = new FormData()
formData.set("time", false) 
formData.set("base_file", fileInput.files[0] )

fetch("/upload/", {
   "credentials": "include",
   "body": formData,
   "headers": headers,
   "method": "POST",
   "mode": "cors"
})

异常的Blob生成文件上传代码

以下代码中,生成的Blob通过saveAs方法可正常保存为本地可打开的zip文件,构造出的对象经校验为File实例,但上传始终报错:

var shpBuffer = await ShapeFileFromGeoJSON(geojson, fileName); 
var base64String = Uint8Array.from(window.atob(shpBuffer), (v) => v.charCodeAt(0));
var shapeFileBlob = new Blob([ base64String ], {type:"application/zip"});
saveAs(shapeFileBlob, fileName);  // 本地保存正常,zip文件可用

var file = new File([shapeFileBlob], 'application.zip', { type: shapeFileBlob.type,});
console.log(file);
// 控制台输出: File {name: 'application.zip', lastModified: 1656002582746, 
// lastModifiedDate: Fri Jun 24 2022 04:43:02 GMT+1200 (New Zealand Standard Time), 
// webkitRelativePath: '', size: 6091726, …}
console.log(file instanceof File);  // 输出true

var headers = new Headers();
headers.set('X-CSRFToken', csrftoken);
var formData = new FormData()
formData.set("time", false) 
formData.set("file", file) 

fetch("/upload/", {
   "credentials": "include",
   "body": formData,
   "headers": headers,
   "method": "POST",
   "mode": "cors"
})

报错信息

POST https://WEBSITE/upload/ 400 (Bad Request)
{success: false, errors: Array(1)}

问题根因
  1. 核心错误:表单字段名不匹配
    正常上传逻辑中后端接收文件的字段名为base_file,但Blob生成文件的上传代码错误将字段名写为file,后端无法读取到预期的文件参数,直接返回400错误。
  2. 存在冗余代码逻辑:先将Uint8Array转为Blob再包装为File的操作没有必要,可直接通过二进制数据构造File实例,不会导致报错但属于多余写法。
  3. 潜在踩坑点:若手动给FormData请求设置Content-Type: multipart/form-data请求头,会覆盖浏览器自动生成的boundary分隔符参数,导致后端无法解析表单内容,也会触发400错误。

注:shapefile格式的zip本身不会影响上传逻辑,本地saveAs可正常打开说明文件二进制内容完全符合要求,不需要额外处理文件内容。

修复后可运行代码
var shpBuffer = await ShapeFileFromGeoJSON(geojson, fileName); 
var uint8Arr = Uint8Array.from(window.atob(shpBuffer), (v) => v.charCodeAt(0));
// 直接通过二进制数据构造File实例,文件名使用实际业务名称,MIME类型设为application/zip
var uploadFile = new File([uint8Arr], `${fileName}.zip`, { type: "application/zip" });

var headers = new Headers();
headers.set('X-CSRFToken', csrftoken);
// 禁止手动设置Content-Type请求头,浏览器会自动填充multipart/form-data及对应的boundary参数
var formData = new FormData();
formData.set("time", false);
// 字段名严格和后端要求保持一致,使用base_file
formData.set("base_file", uploadFile);

fetch("/upload/", {
  "credentials": "include",
  "body": formData,
  "headers": headers,
  "method": "POST",
  "mode": "cors"
})

排查注意事项
  • 上传时表单的字段名必须和后端接口要求完全一致,大小写、拼写均不能出错
  • 所有通过FormData上传文件的请求,都不要手动设置Content-Type请求头
  • 只要本地保存的zip文件可正常打开,说明文件内容没有问题,不需要额外做二进制转码处理
  • 构造File时的文件名不需要固定写死,使用实际业务文件名即可,不会影响接口解析

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 01:15:38