Roman Stefanko
Roman Stefanko

Reputation: 395

How to send data correct axios Error: Multipart: Boundary not found

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

Answers (8)

Aman Kumar Gupta
Aman Kumar Gupta

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

parker
parker

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

Daniel
Daniel

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

bang
bang

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

J.E.C.
J.E.C.

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

Charith Jayasanka
Charith Jayasanka

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

agm1984
agm1984

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

Francis Batista
Francis Batista

Reputation: 1520

You can do this ...

Instantiate a new 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)

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

Using 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

Related Questions