0

我在这里发布这个问题,我一直在阅读许多相关的帖子,但其中任何一个都帮助我使它工作。

这个想法很简单:我有一个基于 MEAN 的应用程序,可以在其中将图像上传到 GridFS - 无需将其本地存储到服务器 - 稍后在浏览器中将其可视化。

所以让我们开始吧。我正在使用angular-file-upload模块从 AngularJS 上传图像。因此,在我的一个 AngularJS 控制器中,我有:

$scope.onFileSelect = function(file) {

   var fileName = file.name;

   $scope.upload = $upload.upload({
       url: '/file/uploadFile', //this is the node route for uploading the file
       headers: {
            'fileName':fileName
       },
       file: file
   }).
   success(function(data, status, headers, config) {
    //DOING STUFF
   }.
   error(function(data, status, headers, config) {
    //DOING OTHER STUFF
   });
}

在我的 Node + Express 服务器中,我正在通过grids-stream模块处理上传请求和下载图像的请求。这使我可以直接在 GridFS 中/从 GridFS 中流式传输和保存图像,而无需暂时将其保存在服务器中。

var mongoose = require('mongoose'),Grid = require('gridfs-stream'),gfs;

mongoose.connection.once('open',function() {
    gfs = Grid(mongoose.connection.db, mongoose.mongo);
});

exports.uploadFile = function(req, res) {
   var fileNameHeader = req.headers['filename'];
   //creating a unique filename
   var name = uuid.v1();
   var extIndex = fileNameHeader.lastIndexOf('.');
   var extension = fileNameHeader.substr(extIndex);
   var fileName = name+extension;

   var writeStream  = gfs.createWriteStream({
       filename: fileName,
       root: 'imagesGrid'
   });
   req.pipe(writeStream);
   writeStream.on('close',function() {
      //DOING STUFF 
   });
}

exports.downloadFile = function(req,res) {  
   var name = req.params.name;
   var readStream = gfs.createReadStream({
      filename: name,
      root: 'imagesGrid'
   });
   res.header({'Content-type': mime.lookup(name)});
   readStream.pipe(res);
};

在客户端,我有这个生成所有 HTML 图像元素的 HTML 指令:

<my-image-draggable ng-repeat="image in userImages">
</my-image-draggable> 

其中my-image-draggable作为其元素之一:

<img ng-src='{{image.imageId.location}}'>

在运行时,{{image.imageId.location}}, 被翻译为(例如):'/file/getFile/2350bcf0-53b4-11e4-9f6b-9fc9a66908c4.jpg',因此,原则上

<img ng-src='/file/getFile/2350bcf0-53b4-11e4-9f6b-9fc9a66908c4.jpg'>

应该downloadFile在服务器中触发 HTTP GET 请求,图像应该从 GridFS 流式传输,并最终显示在浏览器中。问题是图像不显示。

我还尝试在 Angular 控制器中对服务器发送的图像数据进行预处理,以便将其编码为 base64,并在运行时ng-src使其类似于:

'data:image/jpeg;base64,'+Base64.encode(data);  

但它也不起作用。

我也尝试downloadFile手动调用路线,但没有结果。我无法弄清楚为什么这不起作用。我想知道图像是否正确保存到 GridFS。

有什么建议吗?还有其他人遇到过同样的问题吗?

非常感谢!

4

1 回答 1

0

似乎您对 socket.io 的使用已经解决了您的问题,但我只需要为自己解决一些问题,并认为我会分享。

就我而言,我需要能够存储有关图像的信息,例如图像标题。我决定坚持使用包含用户提供的所有输入字段以及文件本身的标准 html 发布表单。我使用Multer作为上传路由的中间件,所以当请求到达我的uploadImg路由时,Multer 已经解析了表单字段和文件。

Multer 将文件存储为临时文件(尚未找到一种方法将其流式传输到gridfs-stream同时仍解析表单字段)。一个快速的解决方案是流式传输保存的临时文件,然后在完成后将其删除。这不是一个非常可扩展的解决方案,但对于我们目前的情况来说已经足够了。

var uploadImg = function(req,res) {
      var writestream = gfs.createWriteStream({
        filename: req.files.file.name,
        mode:'w',
        content_type:req.files.file.mimetype,
        metadata:req.body,
      });
    fs.createReadStream(req.files.file.path).pipe(writestream);

    writestream.on('close', function (file) {
        res.send("Success!");
        fs.unlink(req.files.file.path, function (err) {
          if (err) console.error("Error: " + err);
          console.log('successfully deleted : '+ req.files.file.path );
        });
    });

};

另见:MongoError when uploading a file using mongoose, gridfs-stream and multer

于 2014-11-27T16:15:39.857 回答