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
我在保存通过 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.