[英]Formidable: Parse multipart/form-data request THEN upload file
I have a problem since yesterday with my node express app.从昨天开始,我的 node express 应用程序出现了问题。
The thing what I want to do is the next one:我想做的是下一个:
Middleware 1, step 1 (parse request): Parse the multipart/form-data in req.body with formidable and do what I want to do with the data (such validation), then go to step 2 if all being good.中间件 1,步骤 1(解析请求):使用 formidable 解析 req.body 中的 multipart/form-data 并执行我想对数据执行的操作(例如验证),如果一切正常,则 go 到步骤 2。
Middleware 2, step 2 (upload file): Upload file with formidable (already being parsed)中间件2,第2步(上传文件):使用formidable上传文件(已解析)
Problems:问题:
I know there is a filter function but I really want to have two seperated middlewares.我知道有一个过滤器 function 但我真的想要两个独立的中间件。
Express middlewares快递中间件
const formidable = require('formidable');
// parse request
module.exports.middleware1 = async (req, res, next) => {
const form = formidable({ multiples: true });
form.parse(req, (err, fields, files) => {
if (err) {
next(err);
return;
}
// request parsed
// do what I want to do with the fields (such validation)
console.log(fields)
next()
});
}
// upload file
module.exports.middleware2 = async (req, res, next) => {
const options = {
uploadDir: 'test',
keepExtensions: true,
maxFiles: 1,
filename: function (name, ext, part, form) {
return name
},
filter: function ({name, originalFilename, mimetype}) {
return true
}
}
const form = formidable(options);
form.parse(req, (err, fields, files) => {
if (err) {
next(err);
return;
}
// file uploaded, go to controller
next()
});
}
Front app前端应用
publishPost: function () {
let formData = new FormData()
const post = {
filters: {
...this.postFilters
},
details: {
...this.postDetails
}
}
formData.append('post', JSON.stringify(post))
formData.append('file', this.postMedia.file)
postService.createOne(formData).then((res) => {
if (res) {
postServiceStatus.createOneDone()
}
});
}
If anyone has an idea, I'd be grateful!如果有人有想法,我将不胜感激!
I finally found a solution to my problem !我终于找到了解决问题的方法!
I created a global error handler that handle all the errors on my API, and when an error is related to my route where I created the file (in the first middleware), I delete the file with informations passed in req.file.我创建了一个全局错误处理程序来处理我的 API 上的所有错误,当错误与我创建文件的路径相关时(在第一个中间件中),我删除了包含在 req.file 中传递的信息的文件。
const fs = require('fs')
const { DEFAULT_API_PATH } = process.env
/**
* Handle middlewares errors
* @param {Object} err error object
* @param {String} err.type type of error (service affected by the error)
* @param {String} err.error original error
* @param {String} err.message returned error
* @param {Number} err.status error status
* @returns
*/
module.exports = async (err, req, res, next) => {
if (err.error) console.log(err.error)
// Delete file
if (req.path === `${DEFAULT_API_PATH}/posts/create` && req.file) {
if (fs.existsSync(req.file.path)) {
fs.unlinkSync(req.file.path, function (err) {
console.log(err)
});
}
}
if (err.type && err.type === 'database') return res.status(err.status || 400).send({ error: err.message || 'Une erreur innatendue s\'est produite avec la base de données. Veuillez réessayer dans un instant.' })
else if (err.type && err.type === 'server') return res.status(err.status || 400).send({ error: err.message || 'Une erreur innatendue s\'est produite avec le serveur. Veuillez réessayer dans un instant.' })
return res.status(err.status || 400).send({ error: err.message || 'Une erreur innatendue s\'est produite. Veuillez réessayer dans un instant.' })
}
The server can consume an incoming request only once, because the request body is streamed by the client and the HTTP protocol does not allow the server to request a "rewind" from the client.服务器只能使用一次传入请求,因为请求正文由客户端流式传输,并且 HTTP 协议不允许服务器向客户端请求“倒带”。
The idea of multer
and formidable
is to write the file to the uploadDir
as the request is being consumed . multer
和formidable
的想法是在使用请求时将文件写入uploadDir
。 If you do not want to do that in the first middleware, you need to store the file in a Javascript variable (for example, res.locals.uploadedFile
) and write it to the uploadDir
yourself in the second middleware.如果您不想在第一个中间件中执行此操作,则需要将文件存储在 Javascript 变量(例如
res.locals.uploadedFile
)中,然后在第二个中间件中自行将其写入uploadDir
。 But what would be the advantage of that?但是这样做有什么好处呢? Main memory is more expensive than disk space.
主要 memory 比磁盘空间更昂贵。
Why do you insist on two separate middlewares?为什么你坚持使用两个独立的中间件?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.