【问题标题】:Sails.js checking stuff before uploading files to MongoDB with skipper (valid files, image resizing etc)Sails.js 在使用船长将文件上传到 MongoDB 之前检查内容(有效文件、图像大小调整等)
【发布时间】:2014-10-22 05:10:23
【问题描述】:

我目前正在我的应用程序中创建一个文件上传系统。我的后端是 Sails.js (10.4),它用作我的单独前端 (Angular) 的 API。

我已选择存储要上传到我的 MongoDB 实例的文件,并使用sails 内置的文件上传模块Skipper。我正在使用适配器 skipper-gridfs (https://github.com/willhuang85/skipper-gridfs) 将文件上传到 mongo。

现在,上传文件本身没有问题:我在客户端上使用 dropzone.js,它将上传的文件发送到 /api/v1/files/upload。文件将被上传。

为了实现这一点,我在我的 FileController 中使用以下代码:

module.exports = {
    upload: function(req, res) {
        req.file('uploadfile').upload({
            // ...any other options here...
            adapter: require('skipper-gridfs'),
            uri: 'mongodb://localhost:27017/db_name.files'
        }, function(err, files) {
            if (err) {
                return res.serverError(err);
            }
            console.log('', files);
            return res.json({
                message: files.length + ' file(s) uploaded successfully!',
                files: files
            });
        });
    }
};

现在的问题是:我想在文件上传之前对其进行处理。具体两点:

  1. 检查文件是否被允许:内容类型标头是否与我想要允许的文件类型匹配? (jpeg、png、pdf 等 - 只是基本文件)。
  2. 如果文件是图像,请使用 imagemagick(或类似工具)将其调整为几个预定义的大小。
  3. 添加也将保存到数据库中的文件特定信息:对上传文件的用户的引用,以及对文件所属模型(即文章/评论)的引用。

我不知道从哪里开始或如何实现这种功能。因此,我们将不胜感激任何帮助!

【问题讨论】:

    标签: mongodb file-upload sails.js gridfs skipper


    【解决方案1】:

    好的,在摆弄了一段时间之后,我设法找到了一种似乎可行的方法。

    它可能会更好,但它做了我现在想做的事情:

    upload: function(req, res) {
        var upload = req.file('file')._files[0].stream,
            headers = upload.headers,
            byteCount = upload.byteCount,
            validated = true,
            errorMessages = [],
            fileParams = {},
            settings = {
                allowedTypes: ['image/jpeg', 'image/png'],
                maxBytes: 100 * 1024 * 1024
            };
    
        // Check file type
        if (_.indexOf(settings.allowedTypes, headers['content-type']) === -1) {
            validated = false;
            errorMessages.push('Wrong filetype (' + headers['content-type'] + ').');
        }
        // Check file size
        if (byteCount > settings.maxBytes) {
            validated = false;
            errorMessages.push('Filesize exceeded: ' + byteCount + '/' + settings.maxBytes + '.');
        }
    
        // Upload the file.
        if (validated) {
            sails.log.verbose(__filename + ':' + __line + ' [File validated: starting upload.]');
    
            // First upload the file
            req.file('file').upload({}, function(err, files) {
                if (err) {
                    return res.serverError(err);
                }
    
                fileParams = {
                    fileName: files[0].fd.split('/').pop().split('.').shift(),
                    extension: files[0].fd.split('.').pop(),
                    originalName: upload.filename,
                    contentType: files[0].type,
                    fileSize: files[0].size,
                    uploadedBy: req.userID
                };
    
                // Create a File model.
                File.create(fileParams, function(err, newFile) {
                    if (err) {
                        return res.serverError(err);
                    }
                    return res.json(200, {
                        message: files.length + ' file(s) uploaded successfully!',
                        file: newFile
                    });
                });
            });
        } else {
            sails.log.verbose(__filename + ':' + __line + ' [File not uploaded: ', errorMessages.join(' - ') + ']');
    
            return res.json(400, {
                message: 'File not uploaded: ' + errorMessages.join(' - ')
            });
        }
    
    },
    

    我选择使用本地文件存储,而不是使用 skipper-gridfs,但想法保持不变。同样,它还没有达到应有的完整性,但它是一种验证文件类型和大小等简单内容的简单方法。如果有人有更好的解决方案,请发布:)!

    【讨论】:

      【解决方案2】:

      您可以为.upload() 函数指定回调。示例:

      req.file('media').upload(function (error, files) {
        var file;
      
        // Make sure upload succeeded.
        if (error) {
          return res.serverError('upload_failed', error);
        }
      
        // files is an array of files with the properties you want, like files[0].size
      }
      

      您可以在.upload() 的回调中调用适配器,并从那里上传文件。

      【讨论】:

      • 所以如果我理解正确的话,我应该首先使用默认的 .upload 函数,它将上传的文件存储在 .tmp/uploads 目录中,并在第一个上传函数的回调中我应该执行我的自定义内容(例如检查文件类型等),然后使用 skipper-gridfs 将其发送到 Mongo?我仍然可以在第一个回调中对文件调用 .upload 吗?
      • 我想是的,是的。我在任何地方都没有看到validate() 回调。
      • 也许我在做一些愚蠢的事情,但是当我在回调中尝试以下操作时: files[0].upload({'adapter: require('skipper-gridfs'), uri: 'mongodb ://localhost:27017/evolution_api_v1.files'}, function(err, files) { ... });控制台会吐出“对象没有方法上传”。有点像我预期的那样。另外我觉得有必要上传两次文件有点奇怪。在文件以某种方式上传之前拦截文件会更好。虽然不确定这是否可能:)。
      猜你喜欢
      • 2022-01-10
      • 2014-07-26
      • 2023-04-01
      • 1970-01-01
      • 2016-09-28
      • 2015-04-29
      • 2016-09-30
      • 1970-01-01
      • 2018-02-09
      相关资源
      最近更新 更多