使用本地文件系统文件条目中的 createObjectURL 会导致文件损坏

Using createObjectURL from local file system file entry results in broken file

我的应用程序是一个科尔多瓦应用程序。我尝试为平台浏览器执行以下操作。我知道描述的问题不会发生在真实设备平台上。

我尝试执行以下操作:

  1. 通过 XMLHttpRequest 下载图像文件
  2. 使用来自 XMLHttpRequest 响应的 blob 通过 createObjectURL 显示图像
  3. 将文件写入本地文件系统(使用 cordova-plugin-file 使文件系统 API 在 Firefox 中可用)
  4. 使用本地文件系统中文件中的 blob 通过 createObjectURL 显示图像

我可以从保存的文件创建一个 blob,但之后图像损坏了。

这是代码:

    var filesystem;
    var downloaddir;
    var filename = 'e44498f0b0964152632bd0c82342914b859c543e.jpeg'
    var downloadurl = 'http://adomain.com/public/content_images/'+filename;


    function download(){
      filesystem.root.getFile(
        '/ressources/'+filename, 
        { create: true, exclusive: false }, 
        function (fileEntry) {  

          var oReq = new XMLHttpRequest();

          oReq.open("GET", downloadurl, true);
          oReq.responseType = "blob";
          oReq.onload = function (oEvent) {
            var blob = oReq.response;
            if (blob) {         
              fileEntry.createWriter(function (fileWriter) {                        
                fileWriter.onwriteend = function (e) {
                  console.log(fileEntry.toURL());// Works in Chrome and Firefox, but file URIs cannot be used for security reasons. So image is not displayed if this RUL is used in image src attribute
                  console.log(window.URL.createObjectURL(blob));// work in chrome and firefox. This is what I like to have in the end but using a file.

                  // Now I want to use the file and transform it in a objectURL, this is where I struggle
                  fileEntry.file(function(file){
                    console.log(window.URL.createObjectURL(file));// works in chrome bot not in firefox. Firefox says :"TypeError: Argument 1 is not valid for any of the 1-argument overloads of URL.createObjectURL."

                    var readerBlob = new FileReader();                              
                    readerBlob.onload = function(event){                                    
                      var blob = new Blob([event.target.result], {type: 'image/jpg'});
                      console.log(window.URL.createObjectURL(blob));// blob uri will be created, but image is broken. Here I want to have a working objectURL that work for Chrome and Firefox           
                    };
                    readerBlob.readAsBinaryString(file);
                  });

                };
                fileWriter.onerror = function (e) {
                };
                fileWriter.write(blob);
              });

            } else console.error('we didnt get an XHR response!');
          };
          oReq.send(null);
        }, 
        function (error) {
          console.log('error creating file');
          console.log(error);
        }
      );
    }

    document.addEventListener("deviceready", function(){
      window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
      window.requestFileSystem(window.TEMPORARY, 10 * 1024*1024, function (fs) {
        filesystem = fs;            
        filesystem.root.getDirectory(
          '/ressources/',
          {create:true}, 
          function(dirEntry){
            console.log('download dir created');
            downloaddir = dirEntry;
            download();
          },
          function(error){
          }
        );
      });
    }, false);

发现错误: 我不得不用 readAsArrayBuffer 读取文件。这样就可以了。所以这里是工作代码,也许它可以帮助某人:

    var filesystem;
    var downloaddir;
    var filename = 'e44498f0b0964152632bd0c82342914b859c543e.jpeg'
    var downloadurl = 'http://adomain.com/public/content_images/'+filename;


    function download(){
      filesystem.root.getFile(
        '/ressources/'+filename, 
        { create: true, exclusive: false }, 
        function (fileEntry) {  

          var oReq = new XMLHttpRequest();

          oReq.open("GET", downloadurl, true);
          oReq.responseType = "blob";
          oReq.onload = function (oEvent) {
            var blob = oReq.response;
            if (blob) {         
              fileEntry.createWriter(function (fileWriter) {                        
                fileWriter.onwriteend = function (e) {
                  console.log(fileEntry.toURL());// Works in Chrome and Firefox, but file URIs cannot be used for security reasons. So image is not displayed if this RUL is used in image src attribute
                  console.log(window.URL.createObjectURL(blob));// works in chrome and firefox. This is what I like to have in the end but using a file.

                  // Now I want to use the file and transform it in a objectURL, this is where I struggle
                  fileEntry.file(function(file){
                    //console.log(window.URL.createObjectURL(file));// works in chrome bot not in firefox. Firefox says :"TypeError: Argument 1 is not valid for any of the 1-argument overloads of URL.createObjectURL."

                    var readerBlob = new FileReader();                              
                    readerBlob.onload = function(event){                                    
                      console.log(event.target.result);

                      var blob = new Blob([event.target.result], {type: 'image/jpg'});
                      console.log(window.URL.createObjectURL(blob));// This URL will work in Chrome and Firefox          
                    };
                    readerBlob.readAsArrayBuffer(file);
                  });

                };
                fileWriter.onerror = function (e) {
                };
                fileWriter.write(blob);
              });

            } else console.error('we didnt get an XHR response!');
          };
          oReq.send(null);
        }, 
        function (error) {
          console.log('error creating file');
          console.log(error);
        }
      );
    }

    document.addEventListener("deviceready", function(){
      window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
      window.requestFileSystem(window.TEMPORARY, 10 * 1024*1024, function (fs) {
        filesystem = fs;            
        filesystem.root.getDirectory(
          '/ressources/',
          {create:true}, 
          function(dirEntry){
            console.log('download dir created');
            downloaddir = dirEntry;
            download();
          },
          function(error){
          }
        );
      });
    }, false);