Gre*_*een 38 file-upload mongodb gridfs meteor
Meteor很棒,但它缺乏传统文件上传的原生支持.有几种方法可以处理文件上传:
从客户端,可以使用以下方式发送数据:
在服务器中,文件可以保存到:
这些方法的优缺点是什么以及如何最好地实现它们?我知道还有其他选项,例如保存到第三方网站并获取网址.
Gre*_*een 77
您可以使用Meteor轻松实现文件上传,而无需使用任何其他软件包或第三方
/*** client.js ***/
// asign a change event into input tag
'change input' : function(event,template){
var file = event.target.files[0]; //assuming 1 file only
if (!file) return;
var reader = new FileReader(); //create a reader according to HTML5 File API
reader.onload = function(event){
var buffer = new Uint8Array(reader.result) // convert to binary
Meteor.call('saveFile', buffer);
}
reader.readAsArrayBuffer(file); //read the file as arraybuffer
}
/*** server.js ***/
Files = new Mongo.Collection('files');
Meteor.methods({
'saveFile': function(buffer){
Files.insert({data:buffer})
}
});
Run Code Online (Sandbox Code Playgroud)
Explantion
首先,使用HTML5 File API从输入中获取文件.使用新的FileReader创建阅读器.该文件读作readAsArrayBuffer.这个arraybuffer,如果你是console.log,返回{}并且DDP不能通过网络发送它,所以它必须转换为Uint8Array.
当你把它放在Meteor.call中时,Meteor自动运行EJSON.stringify(Uint8Array)并用DDP发送它.您可以检查chrome console websocket流量中的数据,您将看到类似base64的字符串
在服务器端,Meteor调用EJSON.parse()并将其转换回缓冲区
优点
缺点
/*** client.js ***/
// asign a change event into input tag
'change input' : function(event,template){
var file = event.target.files[0];
if (!file) return;
var xhr = new XMLHttpRequest();
xhr.open('POST', '/uploadSomeWhere', true);
xhr.onload = function(event){...}
xhr.send(file);
}
/*** server.js ***/
var fs = Npm.require('fs');
//using interal webapp or iron:router
WebApp.connectHandlers.use('/uploadSomeWhere',function(req,res){
//var start = Date.now()
var file = fs.createWriteStream('/path/to/dir/filename');
file.on('error',function(error){...});
file.on('finish',function(){
res.writeHead(...)
res.end(); //end the respone
//console.log('Finish uploading, time taken: ' + Date.now() - start);
});
req.pipe(file); //pipe the request to the file
});
Run Code Online (Sandbox Code Playgroud)
说明
抓取客户端中的文件,创建XHR对象,并通过"POST"将文件发送到服务器.
在服务器上,数据通过管道传输到底层文件系统.您还可以在保存之前确定文件名,执行消毒或检查是否已存在等.
优点
缺点
/*** client.js ***/
//same as option 2
/*** version A: server.js ***/
var db = MongoInternals.defaultRemoteCollectionDriver().mongo.db;
var GridStore = MongoInternals.NpmModule.GridStore;
WebApp.connectHandlers.use('/uploadSomeWhere',function(req,res){
//var start = Date.now()
var file = new GridStore(db,'filename','w');
file.open(function(error,gs){
file.stream(true); //true will close the file automatically once piping finishes
file.on('error',function(e){...});
file.on('end',function(){
res.end(); //send end respone
//console.log('Finish uploading, time taken: ' + Date.now() - start);
});
req.pipe(file);
});
});
/*** version B: server.js ***/
var db = MongoInternals.defaultRemoteCollectionDriver().mongo.db;
var GridStore = Npm.require('mongodb').GridStore; //also need to add Npm.depends({mongodb:'2.0.13'}) in package.js
WebApp.connectHandlers.use('/uploadSomeWhere',function(req,res){
//var start = Date.now()
var file = new GridStore(db,'filename','w').stream(true); //start the stream
file.on('error',function(e){...});
file.on('end',function(){
res.end(); //send end respone
//console.log('Finish uploading, time taken: ' + Date.now() - start);
});
req.pipe(file);
});
Run Code Online (Sandbox Code Playgroud)
说明
客户端脚本与选项2中的相同.
根据Meteor 1.0.x mongo_driver.js的最后一行,公开了一个名为MongoInternals的全局对象,您可以调用defaultRemoteCollectionDriver()来返回GridStore所需的当前数据库db对象.在版本A中,MongoInternals也公开了GridStore.当前流星使用的mongo是v1.4.x.
然后在路由中,您可以通过调用var file = new GridStore(...)(API)来创建新的写入对象.然后,您打开该文件并创建一个流.
我还包括一个版本B.在这个版本中,通过Npm.require('mongodb')使用新的mongodb驱动器调用GridStore,这个mongo是撰写本文时最新的v2.0.13.新的API不需要您打开文件,您可以直接调用stream(true)并开始管道
优点
缺点
基准测试 您可以在选项2和选项3中看到,我包括var start = Date.now(),当写入结束时,我在console.log中输出以ms为单位的时间,下面是结果.双核,4 GB RAM,HDD,ubuntu 14.04.
file size GridFS FS
100 KB 50 2
1 MB 400 30
10 MB 3500 100
200 MB 80000 1240
Run Code Online (Sandbox Code Playgroud)
您可以看到FS比GridFS快得多.对于200 MB的文件,使用GridFS需要大约80秒,而FS只需要大约1秒.我没试过SSD,结果可能会有所不同.但是在现实生活中,带宽可能决定了文件从客户端传输到服务器的速度,实现200 MB /秒的传输速度并不典型.另一方面,传输速度~2 MB /秒(GridFS)更为常态.
结论
这绝不是全面的,但您可以决定哪种方案最适合您的需求.
希望很快,流星DDP可以支持gzip,缓存等,GridFS可以更快 ......
| 归档时间: |
|
| 查看次数: |
11357 次 |
| 最近记录: |