reactjs next.js文件通过api路由上传/强大-不工作

eqoofvh9  于 2022-12-03  发布在  React
关注(0)|答案(4)|浏览(157)

我有一个地狱的时间让文件上传工作通过api路由。
在客户端,我提交的文件如下:

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

我对/api/mail/upload的请求如下所示:

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)

然后在路径(/api/mail/upload)中,我尝试使用weightful解析表单数据,最后对文件执行一些操作。
我已经通过在api路由文件的底部包含以下内容来确保禁用内置的正文解析器:

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

这才是正确的做法,对吧?
最后,在api路线,我已经尝试了许多不同的东西,但目前以下是我期望的工作,但它不是..

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
}

这在服务器端和客户端都不会生成任何输出,我希望console.log(fields, files)在服务器端输出文件名等。
有人知道我错过了什么吗?

n53p2ov0

n53p2ov01#

您所需要的只是禁用Next.js内置的主体解析器:https://nextjs.org/docs/api-routes/api-middlewares#custom-config
下面是工作示例:

// Backend
import formidable from 'formidable';

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

export default async (req, res) => {
  const form = new formidable.IncomingForm();
  form.uploadDir = "./";
  form.keepExtensions = true;
  form.parse(req, (err, fields, files) => {
    console.log(err, fields, files);
  });
};

https://gist.github.com/agmm/da47a027f3d73870020a5102388dd820

q9yhzks0

q9yhzks02#

我100%肯定您的问题是由于混合CommonJS导出(即module.exports =)和ES6模块语法(export const config = ...)造成的。
当你这样做的时候,NextJS只看到默认的导出,而看不到你的配置声明,因此继续解析body。这反过来又导致req在传递给formidable的时候已经完成了。
除此之外,代码中的一切看起来都是正确的。

module.exports = async (req, res) => {

export default async (req, res) => {

你应该得到预期的行为。

bnlyeluc

bnlyeluc3#

我相信,如果您在端点内部执行异步操作,那么next.js希望您返回一个承诺,例如

export default (req, res) => {
 const promise = new Promise((resolve, reject) => {

  const form = new formidable.IncomingForm();

  form.parse(req, (err, fields, files) => {
    if (err) reject(err);
    resolve({fields, files});
  })

 })

 return promise.then(({fields, files}) => {
    res.status(200).json({ fields, files })
 })
}
gkl3eglg

gkl3eglg4#

您可以按照下面的说明以简单的方式实现它-〉
从客户端以简单的方式发送文件将是-〉
客户端-〉

const file = e.target.files[0];
const formData = new FormData();
formData.append("file", file);

const { data } = await axios.post("/api/upload",formData)

在后端安装express-强大
后端API将为-〉

import express from 'express';
import expressAsyncHandler from 'express-async-handler';
import formidable from 'express-formidable';

const router = express.Router();
export const config = {
    api: {
       bodyParser: false,
    },
};
     
export default router.post('/upload',formidable() ,expressAsyncHandler(async (req, res) => {
    const {file} = req.files;
    console.log(file);
    // here you can handle the incoming file to send it to cloud
      
}));

express-award将处理所有传入的流,并通过将所有数据存储到“data”变量来为我们提供数据。为了将其存储到任何云(aws s3,cloudinary),请创建一个可读的流,并将其附加到表单数据中,然后发送它。

相关问题