Multer 无法通过 FormData 保存上传的文件

Multer is unable to save uploaded file through FormData

我在保存通过 VueJS 前端发送到 Node + Express 后端的上传文件时遇到了问题。数据通过多部分表单数据从前端发送,因此所有元数据和文件本身都附加在请求正文中。下面是后端的router

import {submitFlag} from '../some/dir/controller.js'

const router = express.Router();
const app = express();
app.use(express.json());


router.post('/submit-flag', [], submitFlag)

和处理来自路由器API请求的后端控制器

import multer from 'multer';
const evidencePathSave = '../uploads/flagEvidence'

export const submitFlag = async (req, res) => {
    const evidenceStorage = multer.diskStorage({
        destination: function (req, file, cb) {
            cb(null, evidencePathSave)
        },
        filename: function (req, file, cb) {
            cb(null, req.body.flagEvidence.name);
        }
    })
    const uploadEvidence = multer({
        storage: evidenceStorage,
        fileFilter: (req, res, cb) => {
            const filetypes = /pdf|doc|docx|txt/;
            const mimetype = filetypes.test(req.body.flagEvidence.type);
            const extname = filetypes.test(path.extname(req.body.flagEvidence.name));
            // if mimetype && extname are true, then no error
            if(mimetype && extname){
                return cb(null, true);
            }
            // if mimetype or extname false, give an error of compatibilty
            return cb("The uploaded file, isn't compatible");
        }
    }).fields([
        {name: 'flagEvidence', maxCount: 1}
    ]);
    uploadEvidence(req, res, function(err) {
        if (err) {
            console.log(err)
            res.status(500).send("Error in Saving");
        }
    })
    res.status(200)
}

该函数不会 return 任何错误或状态 500 消息,但是在检查本地存储时,该文件似乎在任何地方都找不到。去掉文件过滤功能好像不行

前端Vue功能如下

submitFlag(event) {
    this.flagEvidence = event.target.files[0]
    var formData = new FormData()
    formData.append('flagSubject', this.flagSubject)
    formData.append('flagWriteup', this.flagWriteup)
    formData.append('flagEvidence', this.flagEvidence)
    formData.append('userID', this.user._id)
    formData.append('username', this.user.username)
    formData.append('publicationID', this.publicationID)
    formData.append('filename', this.flagEvidence.name)
    axios({
        method: "POST",
        url: serverSide.submitFlag,
        data: formData,
        headers: {"Content-type": "multipart/form-data"}
    })
    .then((res) => {
      this.$router.push({name: "news", query:{id: this.publicationID}})
    })
    .catch(function (error) {
        console.error(error.response);
    });
}

您对 multer 的使用不正确。 multer.fields() returns 一个函数应该作为中间件传递给你的路由。以下是您的情况:

const evidenceStorage = multer.diskStorage({
  destination: function (req, file, cb) { ... },
  filename: function (req, file, cb) {
    cb(null, file.originalname);
  },
});

const uploadEvidence = multer({
  storage: evidenceStorage,
  fileFilter: (req, res, cb) => { ... },
);

router.post(
  '/submit-flag',
  uploadEvidence.fields([{ name: 'flagEvidence', maxCount: 1 }]),
  submitFlag
);

此外,在配置 DiskStorage 时,我会使用 file.originalname 而不是 req.body.flagEvidence.name。在 Node.js.

中处理文件上传时,请查看此免费 Request Parsing in Node.js Guide