我在这里发布了这个问题,我已经阅读了许多相关的帖子,但其中任何一篇都帮助了我。
这个想法很简单:我有一个基于MEAN的应用程序,可以将图像上传到GridFS,而无需将其本地存储到服务器,然后在浏览器中可视化。
让我们开始吧。我正在使用角度文件上传模块从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服务器中,我通过网格流模块处理上传和下载图像的请求。这使我可以直接在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>
其中我的可拖动图像具有,作为其元素之一:
<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
发出HTTPGET请求,图像应该从GridFS流式传输,并最终显示在浏览器中。问题是没有显示图像。
我还尝试在Angular控制器中预处理服务器发送的图像数据,以便将其编码到base64,并在运行时让ng-src
类似于:
'data:image/jpeg;base64,'+Base64.encode(data);
但它也不起作用。
我也尝试过手动调用downloadFile
路由,但没有结果。我不明白为什么这不起作用。我想知道图像是否正确保存到GridFS。
有什么建议吗?还有谁经历过同样的问题?
非常感谢!
您使用socket.io似乎解决了您的问题,但我只是自己解决了其中的一些问题,并想与大家分享。
对于我的情况,我需要能够存储有关图像的信息,如图片说明。我决定坚持使用标准的html post表单,该表单包含用户提供的所有输入字段以及文件本身。我使用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 );
});
});
};
另请参阅:使用mongoose、gridfs流和multer 上传文件时发生MongoError