Reputation: 395
I don't know why I receive on server [Error: Multipart: Boundary not found] and bundle.js:37628 POST http://localhost:8800/exporttocsv 500 (Internal Server Error) When I make post through
<form action="/exporttocsv" method="POST" encType="multipart/form-data">
post works correctly, but through axios
doesn't work.
Please help me fix the mistake
this my code /--client
import axios from 'axios'
var formData = new FormData()
const config = { headers: { 'Content-Type': 'multipart/form-data' } };
export const ipmortToCSV = (file) => dispatch => {
formData.append('file',file)
console.log(formData.getAll('data'))
axios.post('/exporttocsv', {
"UploadCommand": formData
},config)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
//--server
const router = require('express').Router()
var csv = require('csv-express')
const controllers = require('../../controllers/exporttocsv')
var multer = require('multer')
var upload = multer({dest : 'exporttocsv/'})
router.get('/', (req, res) => {
controllers.exportToCsv(req,res)
})
router.post('/',upload.single('file'),(req,res) => {
//controllers.importToCsv(req,res)
})
module.exports = router
Upvotes: 19
Views: 65372
Reputation: 3029
Axios v0.27.x is not able to compute Boundary automatically of multipart/form-data. I was also facing the same issue.
Kindly update your version to v1.x.x ( I am having v1.3.4 while writing the answer)
Look in this thread for more detail - https://github.com/axios/axios/issues/4631
Hope this will help you or somebody else. Thanks!
Happy Coding :-)
Upvotes: 0
Reputation: 1
Okay, I would like to share my solution as I struggled with this problem for almost a day. The issue was caused by an incorrect package version. Around 27.0.0, some changes were made to the form data sending, which resulted in issues with the boundaries. I'm not sure what version you folks are using, but it might be worth checking if this is the cause of your problem.
https://github.com/axios/axios/issues/4631
Upvotes: 0
Reputation: 8687
By default axios do not attach boundary to content type header. You have to do it manually:
axios.post(`${this.baseUrl}/${path}`, formData, {
headers: {
'Content-Type': `multipart/form-data; boundary=${formData.getBoundary()}`,
},
})
It is especially important if you talking to spring server.
In other case you will see exception:
org.apache.tomcat.util.http.fileupload.FileUploadException: the request was rejected because no multipart boundary was found
Upvotes: 6
Reputation: 11
For me add the following code to fixes it.
axios.post('/xxx/Upload', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
transformRequest: (data) => {
return data
},
})
Upvotes: 1
Reputation: 3012
For me the main reason was what the OP did; sending the data
argument of axios.post
as an object ({ key: formDataObj}
) instead of just formDataObj
directly as the arg.
Upvotes: 0
Reputation: 4812
I was struggling with this issue of multipart boundary not found with fetch api calling to a nestjs server. What I tried was to remove the
'Content-Type': 'multipart/form-data'
,
headers so that Fetch api automatically set the headers and it worked. Try it out
Upvotes: 13
Reputation: 17168
I was getting this problem with Axios via JavaScript because the content-type header was multipart-form-data but the boundary was missing.
Based on my research, a good way to handle it is to allow Axios to auto-detect the content type and set the headers correctly itself.
Here is an idea for how to accomplish this:
const formDataWithFiles = hasFiles ? new FormData() : undefined;
if (formDataWithFiles) {
// axios will automatically set the content-type to multipart/form-data if the
// data param is a FormData object
// otherwise, it will use application/json
// (study the Dev Tools > Network tab > XHR tab headers)
Object.keys(modifiedFields)
.forEach(field => formDataWithFiles.append(field, modifiedFields[field]));
}
const { data } = await axios({
method,
url: actionUrl,
data: hasFiles ? formDataWithFiles : modifiedFields,
headers: {
...axios.defaults.headers,
...headers,
},
});
return data;
The above code is in a generic handleSubmit function that can be called from anywhere in the client-side.
Here is the function signature:
const { data } = await this.submitForm({
actionUrl: this.actionUrl,
method: this.method,
modifiedFields: {
...this.modifiedUser,
},
hasFiles: true,
});
In the above code, there are two use cases. The first is the default case, where a normal payload is sent via a flat object. The second is the case when the form has files and you want multipart/form-data
. In this case, we use the FormData
Object as a vessel to instruct Axios to auto-detect the necessary headers and set the correct boundary.
If you do not specify the headers correctly, it is possible to receive an empty $request->all()
Array in Laravel, or perhaps any server such as node.js.
The short answer to my answer is to use the FormData
Object because it contains more information than a plain-old-JavaScript-object. With it, you can also access:
const formData = new FormData();
console.log('boundary:', formData._boundary);
As my annotation above hints towards, use the Dev Tools > Network tab > XHR tab to examine your request headers and make sure you have content-type application/json
or application/x-www-form-urlencoded
for regular form submits and multipart/form-data'
if you are uploading a file.
Upvotes: 2
Reputation: 1520
You can do this ...
FormData
instance.const config = { headers: { 'Content-Type': 'multipart/form-data' } };
let fd = new FormData();
fd.append('file',files[0])
return axios.post("http://localhost:5000/upload", fd, config)
concat
and concat-stream
const concat = require("concat-stream")
const fd = new FormData()
fd.append("hello", "world")
fd.append("file", fs.createReadStream(file))
fd.pipe(concat(data => {
axios.post("/hello", data, {
headers: fd.getHeaders()
})
}))
promise
const promise = new Promise((resolve) => {
const fd = new FormData();
fd.append("hello", "world");
fd.append("file", fs.createReadStream(binaryFile));
fd.pipe(concat({ encoding: 'buffer' }, data => resolve({ data, headers: fd.getHeaders() })));
});
promise.then(({ data, headers }) => axios.post('/hello', data, { headers }));
I hope I've been useful! :)
References:
Upvotes: 28