fetch - Missing boundary in multipart/form-data POST

100,521

Solution 1

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.

Solution 2

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

Solution 3

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;

Solution 4

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

Solution 5

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}

Share:
100,521

Related videos on Youtube

James
Author by

James

learning every day

Updated on March 15, 2022

Comments

  • James
    James about 1 year

    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.

  • sww314
    sww314 about 6 years
    using fetch, I removed the Content-Type header and it worked.
  • Crysfel
    Crysfel about 6 years
    Unbelievable!! I spent hours until I found this!! delete result.headers['Content-Type']; worked for me, thanks!!
  • master_dodo
    master_dodo almost 6 years
    @Crysfel Thanks.. deleting content type worked for me :P
  • sebnukem
    sebnukem almost 6 years
    doesn't work for me. Setting to undefined defaults to text/plain.
  • James
    James almost 6 years
    @sebnukem which browser? I've never seen that happen, I'll admit though, I switched over to using Axios, it has a nicer api / behavior imo
  • sebnukem
    sebnukem almost 6 years
    @James No problem with the browser. I found out that the HTTP library I was using coerced the body payload to a string.
  • James
    James almost 6 years
    @sebnukem which http lib was that? this post is about fetch
  • sebnukem
    sebnukem almost 6 years
    @James, an in-house, proprietary lib
  • Green
    Green over 5 years
    Very well that you told us that boundary is added automatically. We have all known that before.
  • Green
    Green over 5 years
    But why is it so?
  • James
    James over 5 years
    @Green Apparently you can define an arbitrary boundary -> stackoverflow.com/questions/3508338/… -- I just didn't, I only set the content type, but that is only half the job. On the other hand, If you just leave the content type alone, the browser can infer it, and set the type + the boundary to an appropriate compliant, random string for you.
  • Ahab
    Ahab over 5 years
    Neither setting the content-type to undefined, nor deleting the content-type before making the POST with fetch did it for me...
  • James
    James over 5 years
    2 years later, I'd recommend using something like axios unless you absolutely need isomorphic fetch - over the years I've found fetch to be more of a nuisance than a help
  • Oscar Calderon
    Oscar Calderon about 5 years
    Setting value to undefined didn't work for me, but removing header worked :)
  • jaeyow
    jaeyow about 5 years
    explicitly setting Content-Type to undefined worked for me
  • Eugenijus S.
    Eugenijus S. almost 4 years
    your explanation makes much more sense, thank you! I managed to get my code working!
  • iVoidWarranties
    iVoidWarranties over 3 years
    No other solutions worked for me. After adding Accept: / header, everything worked like a charm.
  • Scribblemacher
    Scribblemacher over 2 years
    Setting the Content-Type header to undefined seemed to come across for me as "Content-Type": undefined in the request itself. not defining it worked.