fetch - Missing boundary in multipart/form-data POST

thanks for stopping by.

I want to send a new FormData() as the body of a POST request using the fetch api

the operation looks something like this

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
  }
)

the problem here is that the boundary, something like

boundary=----WebKitFormBoundaryyEmKNDsBKjB7QEqu

never makes it into the Content-Type: header

it should look like this

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

when you try the "same" operation with a new XMLHttpRequest(), like so

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

the headers are correctly set

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

so my question is,

  1. how do I make fetch behave exactly like XMLHttpRequest in this situation?

  2. if this is not possible, why?

Thanks everybody! This community is more or less the reason I have professional success.

Answers:

Answer

The solution to the problem is to explicitly set Content-Type to undefined so that your browser or whatever client you're using can set it and add that boundary value in there for you. Disappointing but true.

Answer
fetch(url,options)
  1. If you set a string as options.body, you have to set the Content-Type in request header ,or it will be text/plain by default.
  2. If options.body is specific object like let a = new FormData() or let b = new URLSearchParams(), you don't have to set the Content-Type by hand.It will be added automaticlly.

    • for a ,it will be something like

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

    as you see, the boundary is automaticlly added.

    • for b, it is application/x-www-form-urlencoded;
Answer

I removed "Content-Type" and added 'Accept' to http headers and it worked for me. Here are the headers I used,

'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' 

      })
Answer

I had the same issue, and was able to fix it by excluding the Content-Type property, allowing the browser to detect and set the boundary and content type automatically.

Your code becomes:

var formData = new FormData()
formData.append('myfile', file, 'someFileName.csv')

fetch('https://api.myapp.com',
  {
    method: 'POST',
    body: formData
  }
)
Answer

I'm using the aurelia-api (an wrapper to aurelia-fetch-client). In this case the Content-Type default is 'application/json'. So I set the Content-Type to undefined and it worked like a charm.

Answer

Add headers:{content-type: undefined} browser will generate a boundary for you that is for uploading a file part-and-part with streaming if you are adding 'multiple/form-data' it means you should create streaming and upload your file part-and-part

So it is okay to add request.headers = {content-type: undefined}

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.