Meteor:ArrayBuffer(FileReader 结果)未传递给 Meteor.method()

Posted

技术标签:

【中文标题】Meteor:ArrayBuffer(FileReader 结果)未传递给 Meteor.method()【英文标题】:Meteor: ArrayBuffer (FileReader result) is not passed to Meteor.method() 【发布时间】:2015-01-08 09:54:39 【问题描述】:

我有这个事件(使用<input type="file"> 上传图像文件):

       "change .logoBusinessBig-upload":function(event, template)

            var reader = new FileReader()

            reader.addEventListener("load", function(evt)

                var x = reader.result

                console.log(x)

                Meteor.call("saveFile", x)

            )

            reader.readAsArrayBuffer(event.currentTarget.files[0])

        

还有这个 Meteor.method()

       saveFile:function(file)

            console.log(file)

            var fs = Npm.require("fs")

            fs.writeFile('../../../../../public/jow.txt', file, function (err) 


                console.log("file saved")

            );

        

事件中的console.log(x)输出一个ArrayBuffer对象,而Meteor.method()中的console.log(file)显示为空 对象。

这是为什么呢? ArrayBuffer 应该已经传递给 Meteor.method()

【问题讨论】:

【参考方案1】:

通过 Meteor 中的方法进行客户端-服务器通信使用 DDP 协议,该协议仅支持 EJSON-able 数据类型,并且不允许传输像您的 ArrayBuffer 这样更复杂的对象,这就是为什么您在服务器。

我建议您 read the file as a binary string,将其发送到您的方法,然后在服务器上对其进行操作(通过 ArrayBuffer 或其他方式)。

【讨论】:

readAsBinaryString 已弃用...我可以使用 DDP 将客户端图像传输到我的 /public 文件夹吗?【参考方案2】:
//client.js

'change': function(event, template) 
    event.preventDefault();
    var file = event.target.files[0]; //assuming you have only 1 file
    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

'saveFile': function(buffer)
    fs.writeFile('/location',new Buffer(buffer),function(error)...);

您无法保存到 /public 文件夹,这会触发重新加载

【讨论】:

你刚刚救了我,伙计!我已经为此研究了整整两个星期!哈哈哈谢谢!【参考方案3】:

看到EJSON 将类型化数组编码为base64 字符串,使用EJSONDateURL 并不重要——它们同样低效(将带宽使用增加30%)。

所以这个:

reader.onload = function(event)          
  var buffer = new Uint8Array(reader.result) // convert to binary
  Meteor.call('saveFile',buffer); // will convert to EJSON/base64


reader.readAsArrayBuffer(file); //read the file as arraybuffer

等价于

reader.onload = function(event)          
  Meteor.call('saveFile',reader.result);


reader.readAsDataURL(file); //read the file DataURL (base 64)

最后一个版本在客户端缩短了一行,但是当您解压缩文件以修剪它的 mime 类型前缀时,会在服务器端添加一行,通常类似于

new Buffer(dataURI.replace(/^data:.1,20\/.1,30;base64,/, ''), 'base64');

替代方案:XHR

所以两者都不是真的更有效。如果您想节省带宽,请尝试使用 XHR 执行此操作,它本机支持所有二进制类型(FileArrayBufferBlob)。您可能需要在 Meteor 之外处理它,可能是作为一个小型 Express 应用程序,其路由由 nginx 等前端代理处理。

【讨论】:

以上是关于Meteor:ArrayBuffer(FileReader 结果)未传递给 Meteor.method()的主要内容,如果未能解决你的问题,请参考以下文章

javascript 将arraybuffer转换为string,将string转换为arraybuffer

ArrayBuffer与字符串的互相转换

ArrayBuffer

JavaScript中的ArrayBuffer该如何理解呢?

scala中arraybuffer 与array有啥区别

如何从对象解码arrayBuffer