简体   繁体   中英

Proper way to send multipart/form-data using `fetch` or `request`

This is the structure of the data I want to send to the server:

{
   attachment: [File],
   foo: String,
   bar: String
}

As you can see, I am trying to send an array of files along with some other data. For storing all this data, I used FormData() constructor provided in the JavaScript official API. I am populating the formData like this:

for (let i = 0; i < this.state.files.length; i++) {
    let f = this.state.files[i];
    this.formData.append('attachment', f, f.name);
}
this.formData.append('foo', this.state.foo);
this.formData.append('bar', this.state.bar);

Sidenote: using React, react-dropzone for file upload. I am now trying to submit this data to the server. I first tried using the Fetch API like so:

fetch(url, {
    method: method,
    body: data,
    headers: {
      ...authHeader(authToken)
    }
}

Without too much success. Method is POST . authHeader(authToken) just generates Authorization: Bearer ... . Problem was I think that the headers that get specified get overridden by my authentication header.

So I tried using request and request-promise-native . I did something like:

rp({
    url,
    method,
    headers: {
      ...authHeader(authToken)
    },
    formData: data
});

With similar results. What is the proper way to send this kind of data with Authorization Header and an array of Files from FormData ?

This are the options available in the fetch object

fetch(url, {
            method: "POST", // *GET, POST, PUT, DELETE, etc.
            mode: "cors", // no-cors, cors, *same-origin
            cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
            credentials: "same-origin", // include, *same-origin, omit
            headers: {
                "Content-Type": "application/json",
                // "Content-Type": "application/x-www-form-urlencoded",
            },
            redirect: "follow", // manual, *follow, error
            referrer: "no-referrer", // no-referrer, *client
            body: JSON.stringify(data), // body data type must match "Content-Type" header
        })

If you need to send some custom header to the server just write it like this:

headers: {
           "My-Custom-Header": "Custom-Header-Value",
         }

And because you want to send a multipart-form data you need to just add the data to the body of the request like this:

body: formData 

If you have your fields inside a form tag you could set your form data like this:

var formData = new FormData(document.querySelector("form"));

If you are using http authentication there are different authentication schemes, for reference use this link https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication

If your are using basic authorization then you should use something like this:

headers: {
           'Authorization': 'Basic '+btoa('username:password')
         }

For future reference, I managed to send the data with the following configuration:

fetch(url, {
    method: method,
    body: data,
    headers: {
        'Accept': 'application/json',
        ...authHeader(authToken)
    }
})

That is, passing through the Accept header seems to have fixed the issue. Please also note that the Content-Type header is not set, allowing browser to set it by itself.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM