ionic2 - Ionic 2/cordova-plugin-file File.writeFile() 拒绝正确创建二进制文件(png 图像)

标签 ionic2 cordova-plugin-file

总结
File.writeFile()尝试写入由 base64 数据制成的 Blob 时,会创建一个 0 字节的 PNG 文件。

在我的应用程序中,我试图创建一个包含存储在数据库中的 base64 数据的文件。数据的渲染等价物是先前从 Canvas 元素创建和存储的透明背景(从不超过 300 x 320 像素)上的黑色抗锯齿小曲线。我已经通过在线提供的各种 base64 编码器/解码器之一独立验证了存储的 base64 数据确实是正确的。

“ ionic 信息”的输出

--------------------------------
Your system information:

Cordova CLI: 6.3.1
Gulp version:  CLI version 3.9.1
Gulp local:
Ionic Framework Version: 2.0.0-rc.2
Ionic CLI Version: 2.1.1
Ionic App Lib Version: 2.1.1
Ionic App Scripts Version: 0.0.39
OS:
Node Version: v6.7.0
--------------------------------

开发平台是 Windows 10,到目前为止,我一直在三星 Galaxy S7 和 S4 上直接进行测试。

我知道必须首先将 base64 数据转换为二进制数据(作为 Blob),因为 File 尚不支持将 base64 直接写入图像文件。我找到了各种技术来做到这一点,并且似乎最适合我需要的代码(并反射(reflect)了我在 java 中完成它的类似方式如下所示):

构造函数的主要代码:
this.platform.ready().then(() => {
      this.graphDataService.getDataItem(this.job.id).then((data) =>{
        console.log("getpic:");

        let imgWithMeta = data.split(",") 
        // base64 data
        let imgData = imgWithMeta[1].trim();
        // content type
        let imgType = imgWithMeta[0].trim().split(";")[0].split(":")[1];

        console.log("imgData:",imgData);
        console.log("imgMeta:",imgType);
        console.log("aftergetpic:");

        // this.fs is correctly set to cordova.file.externalDataDirectory
        let folderpath = this.fs;
        let filename = "dotd_test.png";

        File.resolveLocalFilesystemUrl(this.fs).then( (dirEntry) => {
            console.log("resolved dir with:", dirEntry);
            this.savebase64AsImageFile(dirEntry.nativeURL,filename,imgData,imgType);
        });
      });

    });

将 base64 转换为 Blob 的助手:
// convert base64 to Blob
b64toBlob(b64Data, contentType, sliceSize) {

          //console.log("data packet:",b64Data);
          //console.log("content type:",contentType);
          //console.log("slice size:",sliceSize);

          let byteCharacters = atob(b64Data);

          let byteArrays = [];

          for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
              let slice = byteCharacters.slice(offset, offset + sliceSize);

              let byteNumbers = new Array(slice.length);
              for (let i = 0; i < slice.length; i++) {
                  byteNumbers[i] = slice.charCodeAt(i);
              }

              let byteArray = new Uint8Array(byteNumbers);

              byteArrays.push(byteArray);

          }

        console.log("size of bytearray before blobbing:", byteArrays.length);
        console.log("blob content type:", contentType);

        let blob = new Blob(byteArrays, {type: contentType});

        // alternative way WITHOUT chunking the base64 data
        // let blob = new Blob([atob(b64Data)],  {type: contentType});

        return blob;
  }

使用 File.writeFile() 保存图像
// save the image with File.writeFile()
savebase64AsImageFile(folderpath,filename,content,contentType){

      // Convert the base64 string in a Blob
      let data:Blob = this.b64toBlob(content,contentType,512);

      console.log("file location attempt is:",folderpath + filename);

      File.writeFile(
        folderpath,
        filename,
        data,
        {replace: true}
      ).then(
        _ => console.log("write complete")
      ).catch(
        err => console.log("file create failed:",err);
      );    
  }

我尝试了几十种不同的解码技术,但效果都是一样的。但是,如果我将简单的文本数据硬编码到 writeFile()部分,像这样:
File.writeFile(
        folderpath,
        "test.txt",
        "the quick brown fox jumps over the lazy dog",
        {replace: true}
      )

一个文本文件 IS 在预期位置正确创建 上面的文本字符串。

但是,我注意到无论文件是 0 字节 PNG,还是上面的工作文本文件,在这两种情况下,File Promise 的“.then()”后果子句都不会触发。

此外,我交换了上述方法并使用了 Ionic 2 原生 Base64-To-Gallery 创建图像的库,没有问题的工作 .但是,将图像放在用户的图片库或相机胶卷中对我来说不是一个选择,因为我不希望在编码/打包/传输/删除数据渲染图像时冒用户自己的照片的风险。图像应作为应用程序的一部分创建和管理。

用户 马库斯-罗宾逊似乎遇到了此处概述的类似问题,但它涉及所有文件类型,而不仅仅是二进制类型,就像这里的情况一样。此外,该问题似乎已关闭:

https://github.com/driftyco/ionic/issues/5638

有没有人遇到类似的事情,或者可能发现我可能造成的一些错误?我已经尝试了几十种替代方法,但似乎都没有奏效。

最佳答案

我有类似的行为来保存在 iOS 上完美运行的媒体文件。尽管如此,我在发布版本的某些 Android 设备上遇到了 0 字节文件创建问题(开发版本完美运行)。经过很长时间的搜索,我遵循了以下解决方案

我移动了polyfills.js index.html 顶部的脚本标记在 cordova.js 之前的 ionic 项目中标签。这种重新排序以某种方式解决了问题。

所以顺序应该是这样的:

<script src="build/polyfills.js"></script>
<script type="text/javascript" src="cordova.js"></script>

作品于 ionic 3ionic 4 .

学分转到 1

关于ionic2 - Ionic 2/cordova-plugin-file File.writeFile() 拒绝正确创建二进制文件(png 图像),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40636495/

相关文章:

android - 在 cordova 和 Ionic 中处理文件 - 兼容 iOS、Android

sqlite - 无法插入新行的Sqlite,Ionic2

angular - Ionic3 延迟加载和翻译不能一起工作

ios - cordova-plugin-file 在 ios 上不起作用,无法将捕获的图像保存在文档目录中

ios - 为什么我的 IOS 应用程序拒绝 cdvfile ://and file:///links?

android - Cordova + Android Studio 报错:'com.android.build.gradle.BasePlugin' 没有实现Plugin接口(interface)

android - Cordova 文件插件 - 在设备中保存文件

javascript - ionic 2 : disable scrolling on login form input focus

cordova - "ionic cordova build ios"不工作

angular - 带有推送通知的 Firebase native 插件无法正常工作