I am posting this issue here, I have been reading many related posts, but any of them helped me in making it work.
The idea is pretty easy: I have a MEAN-based application in which is possible to upload an image to GridFS - WITHOUT storing it locally to the server - and later to visualize it in the browser.
So let's start. I am uploading an image from AngularJS by using the angular-file-upload module. Therefore, in one of my AngularJS controller I have:
$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
});
}
In my Node + Express server, I am handling the request to upload and the request to download the image by means of the grids-stream module. This allows me to stream and save the image directly in/from GridFS without the need to save it in the server temporarily.
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);
};
On the client side, I have this HTML directive that generates all HTML image elements:
<my-image-draggable ng-repeat="image in userImages">
</my-image-draggable>
where my-image-draggable has, as one of its elements:
<img ng-src='{{image.imageId.location}}'>
At runtime, {{image.imageId.location}}
, is translated to (for instance): '/file/getFile/2350bcf0-53b4-11e4-9f6b-9fc9a66908c4.jpg'
, thus, in principle
<img ng-src='/file/getFile/2350bcf0-53b4-11e4-9f6b-9fc9a66908c4.jpg'>
should fire a HTTP GET request to downloadFile
in the server, the image should be streamed from GridFS, and finally displayed in the browser. The problem is that the image is not displayed.
I have also tried to pre-process, in the Angular controller, the image data sent by the server in order to encode it to base64 and let at runtime ng-src
be something like:
'data:image/jpeg;base64,'+Base64.encode(data);
but it does not work neither.
I have also tried to call the downloadFile
route manually and it gives no result. I cannot figure it out why this is not working. I am wondering whether the image is correctly saved to GridFS.
Any suggestion? Anyone else who experienced the same issue?
Thanks a lot!