Javascript 从Sails.js中的skipper gridfs下载图像

Javascript 从Sails.js中的skipper gridfs下载图像,javascript,node.js,mongodb,sails.js,gridfs,Javascript,Node.js,Mongodb,Sails.js,Gridfs,我在sails.js应用程序中使用gridfs将图像上传到服务器。我的上传代码如下 upload: function (req, res) { req.file('avatar') .upload({ adapter: require('skipper-gridfs'), uri: 'mongodb://localhost:27017/dbname.images' }

我在sails.js应用程序中使用gridfs将图像上传到服务器。我的上传代码如下

upload: function  (req, res) {
        req.file('avatar')
            .upload({
                adapter: require('skipper-gridfs'),
                uri: 'mongodb://localhost:27017/dbname.images'
            }, function whenDone(err, uploadedFiles) {
                if (err) return res.negotiate(err);
                else return res.ok({
                    files: uploadedFiles,
                    textParams: req.params.all()
                });
            });
    }
我从中得到以下回应

{
    "files": [
        {
            "fd": "2d8910a0-8ca2-4df1-9930-6ddd721a0416.jpg",
            "size": 172883,
            "type": "image/jpeg",
            "filename": "Photo on 12-20-14 at 9.53 PM.jpg",
            "status": "bufferingOrWriting",
            "field": "avatar",
            "extra": {
                "fileId": "54aee6ced4a0e88f0dc9025f",
                "fd": "2d8910a0-8ca2-4df1-9930-6ddd721a0416.jpg",
                "dirname": "."
            }
        }
    ],
    "textParams": {}
}
我的问题是,如果我需要下载上面上传的文件,我该怎么办?我在互联网上获得了下载任务的以下代码,但这对我来说没有多大意义。基本上我想要上传图像的下载url,我可以在移动应用程序中使用该url来显示图像

var blobAdapter = require('skipper-gridfs')({
            uri: 'mongodb://localhost:27017/dbname.images'
        });
        blobAdapter.read(filename, callback);

有人能帮我吗?提前谢谢。

经过研究,我终于解决了这个问题。文件上传后,我在响应中获得字段
fd
,并保存该字段以供以后使用。我转到
skipper gridfs
codes,找到了一个
'read'
方法,该方法接受该值并返回所需的文件。所以,我只是用那个方法从mongo中提取了那个文件,并作为响应发送。这是工作文件

download: function (req, res) {
        var blobAdapter = require('skipper-gridfs')({
            uri: 'mongodb://localhost:27017/mydbname.images'
        });

        var fd = req.param('fd'); // value of fd comes here from get request
        blobAdapter.read(fd, function(error , file) {
            if(error) {
                res.json(error);
            } else {
                res.contentType('image/png');
                res.send(new Buffer(file));
            }
        });
    }

我希望它能在将来帮助像我这样的人:)

除了上面Ayon的优秀答案之外,下面是同一代码的一个版本,它演示了流、持久化文件元数据、动态内容类型和其他一些相关注释:

download: function (req, res) {

  if (!_.isString(req.param('fileId') && !_.isNumber(req.param('fileId')){
    return res.badRequest('`fileId` should be provided as a string/number (depending on whether this is Mongo or MySQL, if you\'ve customized the primary key, etc.).');
  }

  // Look up file metadata
  UploadedFile.findOne({ id: req.param('fileId') })
  .exec(function (err, fileRecord) {
    if (err) { return res.serverError(err); }
    if (!fileRecord) { return res.notFound(); }

    // Get configured blob adapter instance.
    var blobAdapterOpts = _.omit(sails.config.fileUploads, 'adapter');
    var configuredBlobAdapter = sails.config.fileUploads.adapter(blobAdapterOpts);

    // Now locate the actual raw contents of the file using the
    // `fd` that we saved elsewhere (i.e. when uploading), and then
    // use the blob adapter to open up a stream of bytes (the file's
    // contents) and pipe that down as the HTTP response body.  
    // (like skipping a rock across the surface of a pond)
    var fileStream = configuredBlobAdapter.read(fileRecord.fd);
    fileStream.on('error', function (err){
      return res.serverError(err);
    });

    // Along the way, set the content-type for the response based on
    // whatever we saved when this file was originally uploaded.
    // 
    // (You could do the same thing for the filename, assuming this
    // file download is the "save as" kind, as determined by the
    // content-disposition header.)
    res.contentType(fileRecord.contentType);

    // Pipe the stream of file data through as our HTTP response body.
    // (like skipping a rock on the surface of a pond)
    return fileStream.pipe(res);

  });

}
为什么是小溪? 这种流式处理方法使我们不必将整个文件加载到 我们的服务器上的内存(当 处理大型文件,或处理许多并发下载)

错误处理程序 因为我们处理的是userland中的原始节点流/发射器 在这里,我们必须确保绑定一个“错误”事件处理程序 在做任何事情之前,以防万一。(这可防止任何 进程崩溃导致意外的流错误。)

“打开”与“另存文件为” 您可以使用请求参数作为标志来确定 设置内容处置标头,从而确定 用户的浏览器/设备/本机应用程序应“打开”与“另存为” 档案

自定义配置 此示例演示如何设置一些自定义配置。 e、 g.在config/custom.js中,您可以放置: module.exports.custom={ 文件上载:{ 适配器:require('skipper-fs'), uri:'mongodb://localhost:27017/mydbname.images' }, };

行动2呢?
如果您使用的是actions2(在和更高版本中可用),只需将流直接传递到
exits.success()
~~即可完成与
res.pipe()和相关错误处理~~相同的任务。(EDIT:事实上,我对第二部分的理解是错误的——只是仍然需要自己处理
。关于('error',…)
。)此外,您还需要设置内容类型响应标题;i、 e.
env.res.contentType(fileRecord.contentType)

感谢您的分享——这正是正确的方式。非常感谢!也很高兴看到Sails.JS的创建者在这里赞赏我的努力:)我想知道在
res.send()
中创建一个新的缓冲区是否重要/必要,因为(skipper gridfs使用的)返回一个二进制数据缓冲区?是否可以使
res.contentType('image/png')动态以传入任何文件类型(PDF、xls、doc等)@mikermcneil@Ayon@Robert Rossmann抱歉,伙计们,我应该更清楚一点-我最初没有看到示例的结尾。我建议使用流媒体方式,而不是在下载时将整个文件加载到内存中。(即省略cb)因此,您可以执行
var gushingStream=blobAdapter.read(fd),而不是回调;回流喷流管(res)
对于上下文,下面是一个在skipper适配器中实现
read
的示例:除此之外,看起来很棒!