【问题标题】:Parse multipart form data and then upload a file with Multer (Node module)解析多部分表单数据,然后使用 Multer(Node 模块)上传文件
【发布时间】:2016-09-29 13:18:17
【问题描述】:

如果已经将条目添加到数据库中,我在试图弄清楚如何阻止 Multer 上传文件时遇到了一些麻烦。

在我的场景中,我有一个多部分表单,您可以在其中添加指定 id 的啤酒。它有 2 个输入,一个带有文本输入 (id),另一个带有文件输入 (beerImage)。

我想做的是,在上传文件之前,检查它是否已经存在于数据库中,如果不存在,则上传文件。目前,我的代码是先上传文件,然后检查它是否存在,这是一件坏事!

这是我的代码:

var express = require('express');
var router = express.Router();
var multer = require('multer');
var database = require('../services/database');

var upload = multer({ dest: 'uploads/' });
var cpUpload = upload.fields([{ name: 'beerImage', maxCount: 1 } ]);

router.route('/beers')
    .post(function (req, res, next) {
        // I'd like to use req.body.id in the query here, but it doesn't exist yet!
        cpUpload(req, res, function (err) {
            if (err) {
                return next(new Error('Error uploading file: ' + err.message + ' (' + err.field + ')'));
            } else {
                database.getConnection().done(function (conn) {
                    conn.query('SELECT COUNT(*) AS beersCount FROM beers WHERE id=?', req.body.id, function (err, rows, fields) {
                        if (err) {
                            conn.release();
                            return next(err);
                        }

                        if (rows[0].beersCount > 0) {
                            conn.release();
                            return next(new Error('Beer "' + req.body.id + '" already exists!'));
                        } else {
                            delete req.body.beerImage;
                            conn.query('INSERT INTO beers SET ?', req.body, function (err, rows, fields) {
                                conn.release();

                                if (err) {
                                    return next(err);
                                }

                                res.json({ message: 'Beer "' + req.body.id + '" added!' });
                            });
                        }
                    });
                });
            }
        });
    });

module.exports = router;

我找不到一种方法来首先“解析”多部分表单数据(以便能够使用 req.body.id 进行查询并检查它是否存在),然后决定是否要上传文件或不是。似乎“cpUpload”同时做这两件事!

知道如何首先获取“req.body.id”(进行查询)然后决定是否要上传文件吗?

【问题讨论】:

    标签: node.js express multipartform-data multer


    【解决方案1】:
    • 这就是我实现multipart/formdata文件字段和文本字段验证的方法上传到云端。我在multer 中的filterFile 函数如下所示:
    • 请注意,使用邮递员的 formdata 发送的任何数据都被视为multipart/formdata。您必须使用 multer 或其他类似的库来解析表单数据。
    • 对于 x-www-form-urlencodedraw 来自邮递员的数据不需要 multer 进行解析。您可以使用body-parser 或表达内置中间件express.json()express.urlencoded({ extended: false, }) 来解析这些数据
            filterFile = async (req, file, cb) => {
            // if mimetypes are expected mimetypes
    
            const allowedMimeTypes = ["image/jpeg", "image/jpg", "image/png"];
            if (allowedMimeTypes.includes(file.mimetype)) {
              // then validate formdata fields
              // reject the request with error if any validation fails
    
              try {
                let { highlights, specifications, ...rest } = req.body;
    
                // deserializing string into respective javascript object(here into an array datatype) to facilate validation
                highlights = JSON.parse(req.body.highlights);
                specifications = JSON.parse(req.body.specifications);
                
                // constructing deserialized formdata
                const formdata = { highlights, specifications, ...rest };
    
                // using Joi for validation
                let skuAndProductResult = await skuAndProductSchema.validateAsync(
                  formdata
                );
    
                if (skuAndProductResult) {
                  // accept the fields and proceed to the next middleware
                  cb(null, true);
                  return;
                }
    
                // reject the request with error
                cb(true, false);
                return;
              } catch (err) {
                // reject the request with error
                cb(err, false);
              }
            } else {
              // To reject this file pass `false`
              cb(`${file.mimetype} is not supported`, false);
            }
          };
    

    【讨论】:

      【解决方案2】:

      我意识到 Multer 上有一个名为“fileFilter”的功能,您可以在其中控制接受哪些文件。在这里,我已经能够执行所需的查询来检查条目是否存在。

      【讨论】:

        【解决方案3】:

        您必须在测试文件是否存在之前上传文件。然后保存或删除它

        【讨论】:

        • 这是唯一的解决方案,创建一个临时文件吗?
        • 这是对用户的安全保护。您无法在客户端访问该文件。
        • Node.js 在服务器上运行,我想在保存之前检查条目是否存在。
        • 您如何检查文件是否相同?唯一的方法是散列它们(md5,..)并比较校验和。并且对新文件进行hash,之前上传比较方便...
        • 所以让 Multer 将它上传到一个临时文件夹 var upload = multer({ dest: 'tmp/' }); 中,如果它已经存在,则将其删除。否则,将其移动到好文件夹uploads/
        猜你喜欢
        • 2015-10-21
        • 1970-01-01
        • 2019-05-31
        • 2017-11-12
        • 1970-01-01
        • 2018-03-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多