Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

next.js file upload via api routes / formidable - not working

I'm having a hell of a time getting file upload to work via api routes.

On client-side im submitting the file like so:

 onFormSubmit = (e) => {
    e.preventDefault() // Stop form submit

    this.fileUpload(this.state.file).then((response) => {
      console.log('rD', response.data)
    })
 }

 onFileChange = (e) => {
    this.setState({ file: e.target.files[0] })
 }

 fileUpload = (file) => {
    const url = '/api/mail/upload'
    const formData = new FormData()
    formData.append('file', file)
    const config = {
      headers: {
        'X-CSRF-TOKEN': this.props.session.csrfToken
      }
    }
    return axios.post(url, formData, config)
 }

My request to /api/mail/upload then looks like this:

Request Headers:
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,de-DE;q=0.8,de;q=0.7
Connection: keep-alive
Content-Length: 1331
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryBlNt6z8t4rGZT0x6
Cookie: abc123
Host: localhost:3000
Origin: http://localhost:3000
Referer: http://localhost:3000/new
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36
X-CSRF-TOKEN: abc123

Form Data:
file: (binary)

Then in the route (/api/mail/upload) I'm trying to use formidable to parse the form data and finally do something with the file.

I've made sure to disable the built-in body parser by including the following at the bottom of the api route file:

export const config = {
  api: {
    bodyParser: false
  }
}

^^ Thats the correct way to do that, right?

Finally, in the api route, I've tried many different things, but currently the following is what I expect to work, but it is not..

module.exports = async (req, res) => {
  const form = new formidable.IncomingForm()

  form.parse(req, (err, fields, files) => {
    if (err) return reject(err)
    console.log(fields, files)
    res.status(200).json({ fields, files })
  })
  // if I console.log(form) here - I can see the request details, so it seems to be picking that up
}

This generates no output whatsoever on the server-side nor on client-side, i expect the console.log(fields, files) to output on the server-side the name of the file, etc.

Anyone know what I am missing?

like image 386
ndom91 Avatar asked Feb 01 '20 19:02

ndom91


People also ask

Are Next JS API routes serverless?

Serverless functions are not directly a part of the Next.js API. However, Next.js provides developers with API routes that can be deployed on Vercel as serverless functions. And this is the crux of this article.

Can I use Express in next JS API?

Using Express with Next.js, you can: Easily build web socket features in your applications. Develop custom or extra logic for your Next.js routes. Build Express middleware and fetch data for Next.js pages before they are rendered.

Why use API routes next JS?

Next. js API routes allow us to support multiple HTTP verbs for the same endpoint all in one file. The HTTP verbs that we want to support for a single API endpoint are specified in the request handler function. Let's create a pages/api/users/index.

How upload next js file?

Add the following code to the DropZone. js component to handle file upload: ... // to handle file uploads const uploadFiles = async () => { // get the files from the fileList as an array let files = data.


1 Answers

All you need is disable Next.js built-in body parser: https://nextjs.org/docs/api-routes/api-middlewares#custom-config

Here are working example: https://gist.github.com/agmm/da47a027f3d73870020a5102388dd820

like image 166
Lauris Kuznecovs Avatar answered Sep 24 '22 15:09

Lauris Kuznecovs