Изображение, передаваемое из 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