fetch-多部分/表单数据POST中缺少边界

fetch - Missing boundary in multipart/form-data POST

本文关键字:边界 POST 数据 多部 表单 fetch-      更新时间:2023-09-26

我想使用提取api 发送一个new FormData()作为POST请求的body

操作看起来像这样:

var formData = new FormData()
formData.append('myfile', file, 'someFileName.csv')
fetch('https://api.myapp.com', 
  {
    method: 'POST',
    headers: {
      "Content-Type": "multipart/form-data"
    },
    body: formData
  }
)

这里的问题是边界,类似

boundary=----WebKitFormBoundaryyEmKNDsBKjB7QEqu

永远不会进入Content-Type:报头

它应该是这样的:

Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryyEmKNDsBKjB7QEqu

当你尝试";相同的";使用new XMLHttpRequest()操作,类似于

var request = new XMLHttpRequest()
request.open("POST", "https://api.mything.com")
request.withCredentials = true
request.send(formData)

标题正确设置

Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryyEmKNDsBKjB7QEqu

所以我的问题是:

  1. 在这种情况下,我如何使fetch的行为与XMLHttpRequest完全相同
  2. 如果这不可能,为什么

谢谢大家!这个社区或多或少是我在职业上取得成功的原因。

问题的解决方案是显式地将Content-Type设置为undefined,这样您的浏览器或您使用的任何客户端都可以设置它,并在其中添加边界值。令人失望但却是真实的。

我也遇到了同样的问题,并且能够通过排除Content-Type属性来修复它,允许浏览器自动检测和设置边界和内容类型。

您的代码变为:

var formData = new FormData()
formData.append('myfile', file, 'someFileName.csv')
fetch('https://api.myapp.com',
  {
    method: 'POST',
    body: formData
  }
)

我删除了"Content-Type"并在http标头中添加了"Accept",这对我来说很有效

'headers': new HttpHeaders({
        // 'Content-Type': undefined,
        'Accept': '*/*',
        'Authorization': 
        "Bearer "+(JSON.parse(sessionStorage.getItem('token')).token),
        'Access-Control-Allow-Origin': this.apiURL,
        'Access-Control-Allow-Methods': 'GET, POST, OPTIONS, PUT, PATCH, DELETE',
        'Access-Control-Allow-Headers': 'origin,X-Requested-With,content-type,accept',
        'Access-Control-Allow-Credentials': 'true' 
      })
fetch(url,options)
  1. 如果将字符串设置为options.body,则必须在请求头中设置Content-Type,否则默认情况下为text/plain
  2. 如果options.body是特定对象,如let a = new FormData()let b = new URLSearchParams(),则不必手动设置Content-Type。它将自动添加。

    • 对于a,它将类似于

    multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

    正如您所看到的,边界是自动添加的。

    • 对于b,它是application/x-www-form-urlencoded;

根据FormData文档,您不应该手动设置Content-Type标头,这样浏览器本身就会正确设置它:

警告:当使用FormData使用XMLHttpRequest或Fetch_API提交具有多部分/form-data Content-Type的POST请求时(例如,当将文件和Blob上载到服务器时(,请不要在请求上显式设置Content-Type头。这样做将使浏览器无法使用边界表达式设置"内容类型"标头,该边界表达式将用于在请求正文中分隔表单字段。

因此,如果您的代码(或库/中间件等(手动设置Content-Type,则有两种方法可以修复它:

  1. 重写您的代码(或您使用的任何代码(以默认不设置Content-Type
  2. Content-Type设置为undefined,或将其从headers中删除,让浏览器完成工作

Addheaders:{content-type: undefined}浏览器将为您生成边界用于上传文件部分和流式传输部分如果你添加了"多个/表单数据",这意味着你应该创建流媒体并上传你的文件部分和部分

所以可以添加request.headers={content-type:undefined}

我正在使用aureliaapi(aureliafetch客户端的包装器(。在这种情况下,内容类型默认为"application/json"。因此,我将内容类型设置为未定义,它就像一个符咒。