admin管理员组

文章数量:1334949

I upload images to server with gridfs in my sails.js Application. My uploading codes are as follows

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()
                });
            });
    }

I get the following response from this...

{
    "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": {}
}

My question is , if I need to download the uploaded file above , what shall I do ? I got the following code in the internet for downloading task but this does not make much sense to me. Basically I want the download url of the uploaded image that I can use that url in Mobile App to show image.

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

Can anybody help me on this ? Thanks in advance.

I upload images to server with gridfs in my sails.js Application. My uploading codes are as follows

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()
                });
            });
    }

I get the following response from this...

{
    "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": {}
}

My question is , if I need to download the uploaded file above , what shall I do ? I got the following code in the internet for downloading task but this does not make much sense to me. Basically I want the download url of the uploaded image that I can use that url in Mobile App to show image.

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

Can anybody help me on this ? Thanks in advance.

Share Improve this question asked Jan 8, 2015 at 20:26 ayonayon 2,1802 gold badges19 silver badges32 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 9

After some research, I finally managed to solve the problem. I get the field fd in the response after file upload and save that to use afterwards. I went to the skipper-gridfs codes and found a 'read' method that accept that value and returns the required file. So, I just pulled that file from mongo by that method and send as a response. It's working file.

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

        var fd = req.param('fd'); // value of fd es 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));
            }
        });
    }

I hope it will help somebody like me in the future :)

To add to Ayon's excellent answer above, here's a version of the same code that demonstrates streams, persisted file metadata, a dynamic content type, and a couple of other related ments:

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);

  });

}

Why the stream?

This streaming approach saves us from loading the entire file into memory on our server (which would other bee a problem when dealing with large files, or with many concurrent downloads)

The error handler

Since we're dealing with a raw Node stream/emitter in userland code here, we must be sure to bind an 'error' event handler before doing anything-- just in case. (This prevents any unexpected stream errors from crashing the process.)

"open" vs. "save file as"

You could use a request parameter as a flag to determine how to set the content-disposition header -- and thus whether the user's browser/device/native app should "open" vs. "save as" the file.

Custom config

This example demonstrates setting up some custom config. e.g. in config/custom.js, you might put: module.exports.custom = { fileUploads: { adapter: require('skipper-fs'), uri: 'mongodb://localhost:27017/mydbname.images' }, };

What about actions2?

If you're using actions2 (available in Sails v1.x and up), you can acplish the same thing as res.pipe() ~~and the related error handling~~ by simply passing through the stream directly to exits.success(). (EDIT: Actually, I was wrong about the 2nd part of that-- just verified that still have to handle .on('error',...) yourself.) Also, you'll still have to set the content type response header; i.e. env.res.contentType(fileRecord.contentType).

本文标签: javascriptDownload image from skippergridfs in SailsjsStack Overflow