How to Post with Multipart Form Data Using Fetch

How do I POST with multipart form data using fetch?

You're setting the Content-Type to be multipart/form-data, but then using JSON.stringify on the body data, which returns application/json. You have a content type mismatch.

You will need to encode your data as multipart/form-data instead of json. Usually multipart/form-data is used when uploading files, and is a bit more complicated than application/x-www-form-urlencoded (which is the default for HTML forms).

The specification for multipart/form-data can be found in RFC 1867.

For a guide on how to submit that kind of data via javascript, see here.

The basic idea is to use the FormData object (not supported in IE < 10):

async function sendData(url, data) {
const formData = new FormData();

for(const name in data) {
formData.append(name, data[name]);
}

const response = await fetch(url, {
method: 'POST',
body: formData
});

// ...
}

Per this article make sure not to set the Content-Type header. The browser will set it for you, including the boundary parameter.

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

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.

How do I post form data with fetch api?

To quote MDN on FormData (emphasis mine):

The FormData interface provides a way to easily construct a set of key/value pairs representing form fields and their values, which can then be easily sent using the XMLHttpRequest.send() method. It uses the same format a form would use if the encoding type were set to "multipart/form-data".

So when using FormData you are locking yourself into multipart/form-data. There is no way to send a FormData object as the body and not sending data in the multipart/form-data format.

If you want to send the data as application/x-www-form-urlencoded you will either have to specify the body as an URL-encoded string, or pass a URLSearchParams object. The latter unfortunately cannot be directly initialized from a form element. If you don’t want to iterate through your form elements yourself (which you could do using HTMLFormElement.elements), you could also create a URLSearchParams object from a FormData object:

const data = new URLSearchParams();
for (const pair of new FormData(formElement)) {
data.append(pair[0], pair[1]);
}

fetch(url, {
method: 'post',
body: data,
})
.then(…);

Note that you do not need to specify a Content-Type header yourself.


As noted by monk-time in the comments, you can also create URLSearchParams and pass the FormData object directly, instead of appending the values in a loop:

const data = new URLSearchParams(new FormData(formElement));

This still has some experimental support in browsers though, so make sure to test this properly before you use it.

how do I post form data and upload file with the JS fetch API

No need to transform to JSON, and no need to use entries() on FormData. Also check the spelling, you wrote formdata which is different than formData.

const thisForm = document.getElementById('signup');
var formData = new FormData(thisForm);
const profile = document.getElementById('profile');
formData.append("profile", profile.files[0]);
const response = await fetch('<?php echo base_url() . 'api/get_subscription' ?>', {
method: 'POST',
headers: { 'Content-Type': 'multipart/form-data' },
body: formData
});

How to post multipart/formdata using fetch in react-native?

You should have an upload function, which should look like this:

upload(url, data) {
let options = {
headers: {
'Content-Type': 'multipart/form-data'
},
method: 'POST'
};

options.body = new FormData();
for (let key in data) {
options.body.append(key, data[key]);
}

return fetch(requestUrl, options)
.then(response => {
return response.json()
.then(responseJson => {
//You put some checks here
return responseJson;
});
});
}

And you call it this way, sending the image blob path:

this.upload('http://exampleurl.com/someApiCall', {
file: {
uri: image.path,
type: image.mime,
name: image.name,
}
}).then(r => {
//do something with `r`
});

Generate body for multipart file upload using fetch in Javascript

Your metadata is not being properly uploaded if its uploading with a name of unnamed

const fs = require("fs");
const FormData = require("form-data");
const fetch = require("node-fetch");

const filePath = "./sample.txt";
const accessToken = "###";

token = req.body.token;
var formData = new FormData();
var fileMetadata = {
name: "sample.txt",
};
formData.append("metadata", JSON.stringify(fileMetadata), {
contentType: "application/json",
});
formData.append("data", fs.createReadStream(filePath), {
filename: "sample.txt",
contentType: "text/plain",
});
fetch("https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart", {
method: "POST",
body: formData,
headers: { Authorization: "Bearer " + accessToken },
})
.then((res) => res.json())
.then(console.log);

Uploading Files of multipart/form-data to Google Drive using Drive API with Node.js

i am trying to upload a file using fetch API and formData - angular material

It worked when i do not add any headers.

 handleUpload(formData) {
const url = `/upload`;
const proxyurl = 'https://cors-anywhere-proxy.herokuapp.com/';
let result;
const req = new Request(proxyurl + url,
{
method: 'POST',
headers: {},
body: formData
});
fetch(req)
.then(response => response.text())
.then(() => {
if (result.data) {
console.log('result.data', result.data);
} else {
console.log('request failed');
}
})
.catch(() => console.log('Can\'t access ' + url + ' response. Blocked by browser?'));
}

415 on fetch POST with multipart FormData

The older version of Core was not case sensitive when parsing incoming models, the newer version is.

How to send and receive formData through fetch to node and express?

Content-Type

You aren't sending a FormData object. You are sending JSON.

You are passing a string to the body property so you need to explicitly say that you are sending JSON. fetch cannot infer that your string is JSON.

This step wouldn't be needed if you were sending multipart form data by passing a FormData object, nor if you were sending URL Encoded data by passing a URLSearchParams object. fetch can infer the content-type from those objects.

await fetch(`/dbControl/editQuestion?id=${id}`, {
method: "POST",
body: JSON.stringify(dataToSend),
headers: {
"Content-Type": "application/json"
}
});

Body Parsing Middleware

As per the documentation:

Contains key-value pairs of data submitted in the request body. By default, it is undefined, and is populated when you use body-parsing middleware such as express.json() or express.urlencoded().

… you need to include some body parsing middleware.

app.use(express.json());

(And do it before you register the end point handler).

Cannot POST a multipart/form-data using Fetch TYPESCRIPT

UPDATE: I was able to fix it by excluding the Content-Type property, allowing to fetch to detect and set the boundary and content type automatically.

The new code:

const exampleFile = fs.createReadStream(path.join(__dirname, "../lib/dummy.pdf"));

const form = new FormData();
form.append("file", exampleFile);

const requestOptions: RequestInit = {
method: "POST",
body: form
};

await fetch(`https://api.mercadolibre.com/messages/attachments?access_token=${accessToken}`, requestOptions)
.then(response => response.json())
.then(result => console.log(result))
.catch(error => console.log("error", error));


Related Topics



Leave a reply



Submit