Изображение, передаваемое из Gridfs Монго, не отображается в браузере

Я публикую эту проблему здесь, я прочитал много связанных постов, но любой из них помог мне заставить его работать.

Идея довольно проста: у меня есть MEAN-приложение, в котором можно загрузить изображение в GridFS - БЕЗ его сохранения локально на сервере - и позже визуализировать его в браузере.

Итак, начнем. Я загружаю изображение из AngularJS с помощью модуля angular-file-upload. Поэтому в одном из моих контроллеров 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 без необходимости временно сохранять его на сервере.

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'>

должен запустить HTTP GET запрос downloadFile на сервере изображение должно передаваться из GridFS и, наконец, отображаться в браузере. Проблема в том, что изображение не отображается.

Я также попытался предварительно обработать в контроллере Angular данные изображения, отправленные сервером, чтобы закодировать их в base64 и разрешить во время выполнения ng-src быть чем-то вроде:

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

но это не работает ни.

Я также пытался позвонить downloadFile Маршрут вручную, и это не дает результата. Я не могу понять, почему это не работает. Мне интересно, правильно ли изображение сохранено в GridFS.

Любое предложение? Кто-нибудь еще сталкивался с такой же проблемой?

Большое спасибо!

1 ответ

Похоже, что использование 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 при загрузке файла используя mongoose, gridfs-stream и multer

Другие вопросы по тегам