将FileReader ReadAsBinaryString()迁移到ReadAsArrayBuffer()或ReadAsText() [英] Migrate FileReader ReadAsBinaryString() to ReadAsArrayBuffer() or ReadAsText()

查看:508
本文介绍了将FileReader ReadAsBinaryString()迁移到ReadAsArrayBuffer()或ReadAsText()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我意识到,当文件大于200MB(诸如此类)时,新的Mozilla Firefox将返回allocation size overflow(在FileReader.ReadAsBinaryString()上).

I realize that the new Mozilla Firefox return allocation size overflow (on FileReader.ReadAsBinaryString()) when the file bigger than 200MB (something like that).

以下是我针对客户端网络浏览器进行测试的一些代码:

Here's some of my code on test for client web browser:

function upload(fileInputId, fileIndex)
{
    var file = document.getElementById(fileInputId).files[fileIndex];
    var blob;
    var reader = new FileReader();
    reader.readAsBinaryString(file); 
    reader.onloadend  = function(evt)
    {
        xhr = new XMLHttpRequest();

        xhr.open("POST", "upload.php", true);

        XMLHttpRequest.prototype.mySendAsBinary = function(text){
            var data = new ArrayBuffer(text.length);
            var ui8a = new Uint8Array(data, 0);
            for (var i = 0; i < text.length; i++){ 
                ui8a[i] = (text.charCodeAt(i) & 0xff);
            }

            if(typeof window.Blob == "function")
            {
                 blob = new Blob([data]);
            }else{
                 var bb = new (window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder)();
                 bb.append(data);
                 blob = bb.getBlob();
            }

            this.send(blob);
        }

        var eventSource = xhr.upload || xhr;
        eventSource.addEventListener("progress", function(e) {
            var position = e.position || e.loaded;
            var total = e.totalSize || e.total;
            var percentage = Math.round((position/total)*100);
        });

        xhr.onreadystatechange = function()
        {
            if(xhr.readyState == 4)
            {
                if(xhr.status == 200)
                {
                    console.log("Done");
                }else{
                    console.log("Fail");
                }
            }
        };
        xhr.mySendAsBinary(evt.target.result);
    };
}

所以我尝试将其更改为FileReader.ReadAsArrayBuffer(),该错误未显示,但数据不相同(因为它不被读取为二进制字符串).

So I tried change it to FileReader.ReadAsArrayBuffer(), the error has not shown up but the data are not the same (as it's not read as binary string).

有人可以解决此问题吗?除了FileReader的实现之外,还有什么方法可以将原始文件中的较大文件从JS上传到Web服务器?

Did anyone has any solution to solve this problem? Is there any way that we can upload bigger file from JS to Web Server in raw/string other than FileReader implementation?

我在Mozilla JS文档上读到说:

I read on Mozilla JS Documentation that said:

此功能是非标准功能,不在标准范围内.不要 在面向Web的生产站点上使用它:并非对每个人都有效 用户.两者之间也可能存在很大的不兼容性 实施和行为可能会在将来发生变化. - Mozilla

This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future. - Mozilla

如果不是ReadAsBinaryString,如何实现ReadAsArrayBuffer或ReadAsText

If not ReadAsBinaryString, the how to implement ReadAsArrayBuffer or ReadAsText

推荐答案

Kaiido语句正确

Kaiido statement is correct

要将文件发送到Web服务器,您根本不需要js

To send Files to a web-server, you simply don't need js

但这并不能回答我的问题.使用简单的XMLHttpRequest()可以上传文件并跟踪进度.但是,仍然不是.从<form>或使用XMLHttpRequest()直接上传将需要增加php设置中的upload limit.这种方法对我来说不方便.客户端如何将文件上传为4GB?所以我需要增加到4GB.然后下一次,客户端将文件上传为6GB,然后我必须增加到6GB.

But that doesn't answer my question. Using the Simple XMLHttpRequest() can upload the file and track those progress as well. But still, it's not it. The direct upload, either from the <form> or using XMLHttpRequest() will need to increase your upload limit in php setting. This method is not convenience for me. How if the client upload file as 4GB? So I need to increase to 4GB. Then next time, client upload file as 6GB, then I have to increase to 6GB.

对于较大的文件,使用slice()方法是有意义的,因为我们可以将其部分地发送到服务器.但这一次我还没有使用它.

Using the slice() method is make sense for bigger file as we can send it part by part to server. But this time I am not using it yet.

这是我想要的部分测试.我希望如果我错了,专家可以纠正我. 我的Upload.js

Here's some of my test the worked as I want. I hope some expert could correct me if I am wrong. My Upload.js

function upload(fileInputId, fileIndex)
{
    var file = document.getElementById(fileInputId).files[fileIndex];
    var blob;
    var reader = new FileReader();

    reader.readAsArrayBuffer(file);
    reader.onloadend  = function(evt)
    {
        xhr = new XMLHttpRequest();
        xhr.open("POST", "upload.php?name=" + base64_encode(file.name), true);

        XMLHttpRequest.prototype.mySendAsBinary = function(text){
            var ui8a = new Uint8Array(new Int8Array(text));

            if(typeof window.Blob == "function")
            {
                 blob = new Blob([ui8a]);
            }else{

                var bb = new (window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder)();
                bb.append(ui8a);
                blob = bb.getBlob();
            }

            this.send(blob);
        }

        var eventSource = xhr.upload || xhr;
        eventSource.addEventListener("progress", function(e) {
            var position = e.position || e.loaded;
            var total = e.totalSize || e.total;
            var percentage = Math.round((position/total)*100);
            console.log(percentage);
        });

        xhr.onreadystatechange = function()
        {
            if(xhr.readyState == 4)
            {
                if(xhr.status == 200)
                {
                    console.log("Done");
                }else{
                    console.log("Fail");
                }
            }
        };

        xhr.mySendAsBinary(evt.target.result);
    };
}

下面是PHP服务器如何从JS监听ArrayBuffer

Below is how the PHP server listen to the ArrayBuffer from JS

if(isset($_GET["name"])){
    $name = base64_decode($_GET["name"]);
    $loc = $name;
    $inputHandler = fopen('php://input', "r");
    $fileHandler = fopen($loc, "w+");

    while(true) {
        //$buffer = fgets($inputHandler, 1024);
        $buffer = fread($inputHandler, 1000000);

        if (strlen($buffer) == 0) {
            fclose($inputHandler);
            fclose($fileHandler);
            return true;
        }

        //$b = base64_encode($buffer);

        fwrite($fileHandler, $buffer);
    }
}

以上方法效果很好. FileReader将文件读取为ArrayBuffer,上传到服务器.对我来说,从ReadAsBinaryString()迁移到ReadAsArrayBuffer()很重要,并且ReadAsArrayBuffer()的性能要好于ReadAsBinaryString()

The above method works well. The FileReader read the file as ArrayBuffer the upload to server. For me, migrating from ReadAsBinaryString() to ReadAsArrayBuffer() is important and ReadAsArrayBuffer() has some better performance rather than ReadAsBinaryString()

这是某些开发人员依赖FileReader API的原因:

Here's some reason, why some developer relies to FileReader API:

  1. 流式传输.使用此方法,文件将成为流文件,因此我们可以避免多次设置php.
  2. 轻松加密.由于文件是通过ArrayBuffer发送的,因此开发人员在上传过程中很容易Encrypt文件.
  1. Streaming. Using this method, the file will be stream, so we can avoid setting the php multiple time.
  2. Easy Encrypt. As the file is sending via ArrayBuffer, it is easy for developer to Encrypt the file while upload in progress.

此方法还支持上传任何类型的文件.我做了一些测试,我发现ReadAsArrayBuffer()方法比ReadAsBinaryString()和直接表单上传更快.您可以尝试一下.

This method also support upload any type of file. I ve done some test and I realize that ReadAsArrayBuffer() method are more faster than ReadAsBinaryString() and direct form upload. You may try it.

安全公告

以上代码仅在测试代码下,要在生产环境中使用它,您必须考虑在HTTPS下以GETPOST发送数据.

The above code is only under test code, to use it in production, you have to consider sending the data in GET or POST under HTTPS.

这篇关于将FileReader ReadAsBinaryString()迁移到ReadAsArrayBuffer()或ReadAsText()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆