req.form不是实例化的多方表单对象

时间:2014-05-17 23:57:49

标签: node.js express upload middleware multipart

我正在使用具有多部分中间件的快速节点框架。设置multipart defer: true选项可以让我访问路由中的req.form,但它似乎不是多方表单对象的有效实例。它只是一个普通的旧JS对象。

问题是我无法使用multiparty's documentation on the Form Object中列出的功能。听取事件,解析表单等都不起作用。

我使用这个作为建议而不是使用express:

的折旧bodyParser()
app.use(express.urlencoded());
app.use(express.json());
app.use(express.multipart({ limit: '900mb', defer: true }));

在我的路线中:

app.post('/api/videos/upload', isLoggedIn, function(req, res) {
    var form = req.form;
    form.on('progress', function(bytesReceived, bytesExpected) {
        console.log(bytesReceived + ' / ' + bytesExpected);
    });

我在日志中没有得到关于进度的任何信息。我看到的所有例子都假设这个表单对象是真正的交易而不仅仅是数据对象。他们有什么不同的做法?我错过了什么?

我见过建议编写自己的中间件直接使用multiparty的解决方案。我考虑过这个,但是我在不同路径上使用多部分中间件用于不需要这种控制级别的其他形式。是否可以使用multipart并编写我自己的中间件只是为了上传?

如果我要走下一个兔子洞,我会解释我的最终目标。我想在上传开始之前检查预期的字节,这样我就可以立即将其踢回前端。没有理由用户在发现文件太大之前应该等待900MB上传。如果有人对如何实现其他方式有任何见解请分享。

1 个答案:

答案 0 :(得分:5)

当你使用express.multipart()时,你仍然使用不推荐使用的express.bodyParser()解释here

因此,我们必须直接替换以下解析器/中间件之一:

  1. 强大

  2. connect-multiparty或[multiparty]

  3. connect-busboy或busboy

  4. 我直接选择了multiparty API。

    在你的路线中:

    var multiparty = require('multiparty'),
        fs = require('fs'),
        uuid = require('node-uuid');
    
    app.post('/api/videos/upload', function(req, res) {
    
      var size = '';
      var file_name = '';
      var destination_path = '';
    
      // Instatiation in order to use the API options multiparty.Form({options})
      var form = new multiparty.Form();
    
      form.on('error', function (err) {
        console.log('Error parsing form: ' + err.stack);
      });
    
      form.on('part', function (part) {
        if (!part.filename)
            return;
        size = part.byteCount;
        file_name = part.filename;
      });
    
      form.on('file', function (name, file) {
        var temporal_path = file.path;
        var extension = file.path.substring(file.path.lastIndexOf('.'));
        destination_path = './public/uploads/' + uuid.v4() + extension;
        var input_stream = fs.createReadStream(temporal_path);
        var output_stream = fs.createWriteStream(destination_path);
        input_stream.pipe(output_stream);
    
        input_stream.on('end',function() {
            fs.unlinkSync(temporal_path);
            console.log('Uploaded : ', file_name, size / 1024 | 0, 'kb', file.path, destination_path);
        });
      });
    
      form.on('close', function(){
        res.end('Uploaded!');
      });
    
      form.parse(req);
    
    });
    

    你在前端使用了什么?为了在上传之前获取文件的大小,您可以使用AngularJS进行即时双向数据绑定。有一个很好的angular-file-upload模块可以与上面的实现一起使用。但是,如果您想为multipart / form-data编写自己的bodyParser,可以按如下方式覆盖它:

    require('express').bodyParser.parse['multipart/form-data'] = function yourHandler(req, options, next)...