简体   繁体   English

使用 XHR2 请求而不是cordova-file-transfer 将二进制数据下载到应用程序沙箱中

[英]Download binary data into the app sandbox using XHR2 request instead of cordova-file-transfer

Cordova is "sunsetting" (going to deprecate) cordovan-plugin-file, see their blogpost . Cordova 是“日落”(将要弃用)cordovan-plugin-file,请参阅他们的博客文章

No more work will be done on the file-transfer plugin by the Cordova development community. Cordova 开发社区将不再对文件传输插件进行任何工作。 You can continue to use the file-transfer plugin if you wish - it should work fine as-is for the foreseeable future.如果您愿意,您可以继续使用文件传输插件 - 在可预见的未来它应该可以正常工作。 We highly suggest Cordova users transition to using the standards-compliant way of sending and receiving binary data.我们强烈建议 Cordova 用户过渡到使用符合标准的方式发送和接收二进制数据。

They are encouraging a transition to use XHR2 requests (XHR Requests where the responseType is set to Blob or ArrayBuffer .他们鼓励过渡到使用 XHR2 请求(XHR 请求,其中responseType设置为BlobArrayBuffer

The blog post wants to provide an example how binary data can be fetched using XHR2:博文想提供一个如何使用 XHR2 获取二进制数据的示例:

window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) {
console.log('file system open: ' + fs.name);
fs.root.getFile('bot.png', { create: true, exclusive: false }, function (fileEntry) {
    console.log('fileEntry is file? ' + fileEntry.isFile.toString());
    var oReq = new XMLHttpRequest();
    // Make sure you add the domain name to the Content-Security-Policy <meta> element.
    oReq.open("GET", "http://cordova.apache.org/static/img/cordova_bot.png", true);
    // Define how you want the XHR data to come back
    oReq.responseType = "blob";
    oReq.onload = function (oEvent) {
        var blob = oReq.response; // Note: not oReq.responseText
        if (blob) {
            // Create a URL based on the blob, and set an <img> tag's src to it.
            var url = window.URL.createObjectURL(blob);
            document.getElementById('bot-img').src = url;
            // Or read the data with a FileReader
            var reader = new FileReader();
            reader.addEventListener("loadend", function() {
               // reader.result contains the contents of blob as text
            });
            reader.readAsText(blob);
        } else console.error('we didnt get an XHR response!');
    };
    oReq.send(null);
}, function (err) { console.error('error getting file! ' + err); });}, function (err) { console.error('error getting persistent fs! ' + err); });


I have some issues understanding the code above and the intention of cordova to drop the file-tranfer plugin in favour of directly fetching the Blobs via Ajax.我在理解上面的代码和cordova 打算放弃文件传输插件以支持通过Ajax 直接获取Blob 的意图时遇到了一些问题。

Am I seeing this right: fs.root.getFile creates a file.我看对了fs.root.getFilefs.root.getFile创建一个文件。 The download success handler ( oReq.onload ) does not attempt to write the fetched blob to the created file.下载成功处理程序 ( oReq.onload ) 不会尝试将获取的 blob 写入创建的文件。 There is no clear reason why the fileEntry is created.创建 fileEntry 没有明确的原因。 If I would want to save the fetched blob to the created FileEntry, within oReq.onload I could go on using a FileWriter, but only for small (I read up to 5 MB) files (since the Blob is handled in-memory).如果我想将获取的 blob 保存到创建的 FileEntry,在oReq.onload我可以继续使用 FileWriter,但仅适用于小(我读取最多 5 MB)文件(因为 Blob 在内存中处理)。 The blog post is more about how a blob can be fetched in general and not about it can be downloaded into the filesystem.这篇博文更多地是关于一般如何获取 blob,而不是关于它可以下载到文件系统中。 If I would want to download bigger files (like a couple of 100 MB), moving away from cordova-plugin-filetransfer is not an option at the moment.如果我想下载更大的文件(比如几个 100 MB),目前不能选择放弃 cordova-plugin-filetransfer。

With this code you can download big images as they are written by blocks of 1MB instead of doing the whole write at once.使用此代码,您可以下载大图像,因为它们是由 1MB 块写入的,而不是一次完成整个写入。 Without the 1MB writting I wasn't able to write files bigger than 4MB, but with this I've tested with files up to 40MB without problems没有 1MB 的写入,我无法写入大于 4MB 的文件,但是有了这个,我已经测试了最大 40MB 的文件没有问题

 window.resolveLocalFileSystemURL(cordova.file.externalDataDirectory, 
    function (dirEntry) {
        console.log('file system open: ' + dirEntry.name);
        createFile(dirEntry, "downloadedImage.jpg");
    }, onFSError);
    function onFSError(error) {
        alert(JSON.stringify(error));
    }
    function createFile(dirEntry, fileName) {
        // Creates a new file or returns the file if it already exists.
        dirEntry.getFile(fileName, {create: true, exclusive: false}, function(fileEntry) {

            var xhr = new XMLHttpRequest();
            xhr.open('GET', 'https://static.vix.com/es/sites/default/files/styles/large/public/imj/3/30-cosas-de-los-gatos-que-no-sabias-3.jpg', true);
            xhr.responseType = 'blob';

            xhr.onload = function() {
                if (this.status == 200) {
                    var blob = new Blob([this.response], { type: 'image/jpeg' });
                    writeFile(fileEntry, blob);
                }
            };
            xhr.send();
        }, onFSError);
    }

    function writeFile(fileEntry, data) {
       // Create a FileWriter object for our FileEntry (log.txt).
       fileEntry.createWriter(function (fileWriter) {

            fileWriter.onerror = function(e) {
                console.log("Failed file write: " + e.toString());
            };

            function writeFinish() {
                function success(file) {
                    alert("Wrote file with size: " + file.size);
                }
                function fail(error) {
                    alert("Unable to retrieve file properties: " + error.code);
                }
                fileEntry.file(success, fail);
            }
            var written = 0;
            var BLOCK_SIZE = 1*1024*1024; // write 1M every time of write
            function writeNext(cbFinish) {
                fileWriter.onwrite = function(evt) {
                    if (written < data.size)
                        writeNext(cbFinish);
                    else
                        cbFinish();
                };
                if (written) fileWriter.seek(fileWriter.length);
                fileWriter.write(data.slice(written, written + Math.min(BLOCK_SIZE, data.size - written)));
                written += Math.min(BLOCK_SIZE, data.size - written);
            }
            writeNext(writeFinish);
        });
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM