Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mongodb Meteor:将文件从客户端上传到Mongo集合vs文件系统vs GridFS_Mongodb_File Upload_Meteor_Gridfs - Fatal编程技术网

Mongodb Meteor:将文件从客户端上传到Mongo集合vs文件系统vs GridFS

Mongodb Meteor:将文件从客户端上传到Mongo集合vs文件系统vs GridFS,mongodb,file-upload,meteor,gridfs,Mongodb,File Upload,Meteor,Gridfs,Meteor很棒,但它缺乏对传统文件上传的本地支持。有几个选项可用于处理文件上载: 从客户端,可以使用以下方式发送数据: Meteor.call('saveFile',data)或collection.insert({file:data}) “POST”窗体或HTTP.call('POST') 在服务器中,文件可以保存到: 按collection.insert({file:data})的mongodb文件集合 文件系统位于/path/to/dir中 mongodb网格 这些方法的优缺点是

Meteor很棒,但它缺乏对传统文件上传的本地支持。有几个选项可用于处理文件上载:

从客户端,可以使用以下方式发送数据:

  • Meteor.call('saveFile',data)或collection.insert({file:data})
  • “POST”窗体或HTTP.call('POST')
在服务器中,文件可以保存到:

  • 按collection.insert({file:data})的mongodb文件集合
  • 文件系统位于/path/to/dir中
  • mongodb网格

这些方法的优缺点是什么?如何最好地实施它们?我知道还有其他选项,例如保存到第三方网站并获取url。

您可以使用Meteor实现文件上传,而无需使用任何其他软件包或第三方

选项1:DDP,将文件保存到mongo集合
/***client.js***/
//将更改事件指定到输入标记中
“更改输入”:函数(事件、模板){
var file=event.target.files[0];//假设只有1个文件
如果(!文件)返回;
var reader=new FileReader();//根据HTML5文件API创建读取器
reader.onload=函数(事件){
var buffer=new Uint8Array(reader.result)//转换为二进制
Meteor.call('saveFile',buffer);
}
reader.readAsArrayBuffer(文件);//将文件作为arraybuffer读取
}
/***server.js***/
Files=新的Mongo.Collection('Files');
流星法({
“保存文件”:函数(缓冲区){
insert({data:buffer})
}   
});
解释

首先,使用HTML5文件API从输入抓取文件。读卡器是使用新的FileReader创建的。该文件被读取为readAsArrayBuffer。如果您使用console.log,这个arraybuffer将返回{},DDP无法通过线路发送,因此必须将其转换为Uint8Array

当您将其放入Meteor.call中时,Meteor会自动运行EJSON.stringify(Uint8Array)并将其与DDP一起发送。您可以在chrome控制台websocket流量中检查数据,您将看到一个类似base64的字符串

在服务器端,Meteor调用EJSON.parse()并将其转换回缓冲区

专业人士

  • 简单,没有黑客的方式,没有额外的软件包
  • 坚持导线原理上的数据
  • 缺点

  • 更多带宽:生成的base64字符串比原始文件大约33%
  • 文件大小限制:无法发送大文件(限制~16 MB?)
  • 无缓存
  • 还没有gzip或压缩
  • 如果发布文件,会占用大量内存

  • 选项2:XHR,从客户端发布到文件系统
    /***client.js***/
    //将更改事件指定到输入标记中
    “更改输入”:函数(事件、模板){
    var file=event.target.files[0];
    如果(!文件)返回;
    var xhr=new XMLHttpRequest();
    xhr.open('POST','/uploadwhere',true);
    xhr.onload=函数(事件){…}
    发送(文件);
    }
    /***server.js***/
    var fs=净现值要求(“fs”);
    //使用interal webapp或iron:router
    WebApp.connectHandlers.use('/uploadwhere',函数(req,res){
    //var start=Date.now()
    var file=fs.createWriteStream('/path/to/dir/filename');
    on('error',函数(error){…});
    on('finish',function(){
    文书标题(…)
    res.end();//结束响应
    //console.log('完成上传,所用时间:'+Date.now()-start);
    });
    req.pipe(文件);//将请求通过管道传输到文件
    });
    
    解释

    抓取客户端中的文件,创建XHR对象,并通过“POST”将文件发送到服务器

    在服务器上,数据通过管道传输到底层文件系统。您还可以在保存之前确定文件名、执行清理或检查文件名是否已存在等

    专业人士

  • 利用XHR 2,您可以发送arraybuffer,与选项1相比,不需要新的FileReader()
  • 与base64字符串相比,Arraybuffer的体积更小
  • 没有大小限制,我在localhost中发送了一个约200 MB的文件,没有问题
  • 文件系统的速度比mongodb快(后面的基准测试将介绍更多这方面的内容)
  • 可计算和gzip
  • 缺点

  • XHR 2在较旧的浏览器中不可用,例如IE10以下的浏览器,但是您当然可以实现一个传统的post。我只使用了XHR=new XMLHttpRequest(),而不是HTTP.call(“post”),因为Meteor中当前的HTTP.call还不能发送arraybuffer(如果我错了,请告诉我)
  • /path/to/dir/必须在meteor之外,否则在/public中写入文件会触发重新加载

  • 选项3:XHR,保存到GridFS
    /***client.js***/
    //与方案2相同
    /***版本A:server.js***/
    var db=MongoInternals.defaultRemoteCollectionDriver().mongo.db;
    var GridStore=mongonternals.NpmModule.GridStore;
    WebApp.connectHandlers.use('/uploadwhere',函数(req,res){
    //var start=Date.now()
    var file=newgridstore(db,'filename','w');
    打开(函数(错误,gs){
    file.stream(true);//管道完成后,true将自动关闭文件
    on('error',函数(e){…});
    on('end',function(){
    res.end();//发送端响应
    //console.log('完成上传,所用时间:'+Date.now()-start);
    });
    请求管道(文件);
    });     
    });
    /***版本B:server.js***/
    var db=MongoInternals.defaultRemoteCollectionDriver().mongo.db;
    var GridStore=Npm.require('mongodb').GridStore//还需要在package.js中添加Npm.depends({mongodb:'2.0.13'})
    WebApp.connectHandlers.use('/uploadwhere',函数(req,res){
    //var start=Date.now()
    var file=new GridStore(db,'filename','w')。stream(true);//启动流
    on('error',函数(e){…});
    on('end',function(){
    res.end();//发送端响应
    //控制台
    
    file size   GridFS  FS
    100 KB      50      2
    1 MB        400     30
    10 MB       3500    100
    200 MB      80000   1240
    
    <template name='tryUpload'>
      <p>Choose file to upload</p>
      <input name="upload" class='fileupload' type='file'>
    </template>
    
    Template.tryUpload.events({
    'change .fileupload':function(event,template){
    console.log('change & view');
    var f = event.target.files[0];//assuming upload 1 file only
    if(!f) return;
    var r = new FileReader();
    r.onload=function(event){
      var buffer = new Uint8Array(r.result);//convert to binary
      for (var i = 0, strLen = r.length; i < strLen; i++){
        buffer[i] = r.charCodeAt(i);
      }
      var toString = String.fromCharCode.apply(null, buffer );
      console.log(toString);
      //Meteor.call('saveFiles',buffer);
    }
    r.readAsArrayBuffer(f);};