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

4

我有一个事件(使用<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()。
3个回答

10
//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 文件夹,因为这会触发重新加载。

你救了我大忙啊!我已经研究了整整两周了,哈哈哈,谢谢你! - nickanor

2
通过 Meteor 中的方法进行客户端-服务器通信使用 DDP 协议,该协议仅支持可转换为 EJSON 的数据类型,并且不允许传输更复杂的对象,例如 ArrayBuffer,这就是为什么您在服务器上看不到它的原因。
我建议您将文件作为二进制字符串读取,然后像这样将其发送到您的方法中,在它到达服务器后对其进行操作(无论是通过 ArrayBuffer 还是其他方式)。

"readAsBinaryString 已被弃用...我可以使用 DDP 将客户端图像传输到我的 /public 文件夹吗?" - kevinius

0

由于 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 处理路由。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接