Reputation: 5777
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 questions are:
fetch
behave exactly like XMLHttpRequest
in this situation?Thanks everybody! This community is more or less the reason I have professional success.
Upvotes: 144
Views: 208894
Reputation: 2932
I just use axios and it fixed without any special parameters. the node fetch really sucks
Upvotes: 0
Reputation: 201
According to FormData documentation, you shoudn't manually set the Content-Type
header so browser itself will set it correctly:
Warning: When using FormData to submit POST requests using XMLHttpRequest or the Fetch_API with the multipart/form-data Content-Type (e.g. when uploading Files and Blobs to the server), do not explicitly set the Content-Type header on the request. Doing so will prevent the browser from being able to set the Content-Type header with the boundary expression it will use to delimit form fields in the request body.
So if your code (or library/middleware/etc) manually set the Content-Type
, you have two ways to fix it:
Content-Type
by defaultContent-Type
to undefined
or remove it from headers
to let your browser do it's workUpvotes: 19
Reputation: 3940
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
}
)
Upvotes: 31
Reputation: 969
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'
})
Upvotes: 22
Reputation: 621
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}
Upvotes: 6
Reputation: 169
fetch(url,options)
options.body
, you have to set the Content-Type
in request header ,or it will be text/plain
by default.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.
a
,it will be something likemultipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
as you see, the boundary is automaticlly added.
b
, it is application/x-www-form-urlencoded;
Upvotes: 15
Reputation: 5777
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.
Upvotes: 258
Reputation: 321
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.
Upvotes: 4