【问题标题】:Phonegap Plugin:How to convert Base64 String to a PNG image in AndroidPhonegap 插件:如何在 Android 中将 Base64 字符串转换为 PNG 图像
【发布时间】:2012-07-09 01:03:35
【问题描述】:

Android 不允许原生应用(如基于 Phonegap 的应用)写入二进制文件。一个常见的应用是将 Base64 字符串转换为图像。那么,你是如何解决这个问题的呢?

【问题讨论】:

    标签: android image cordova base64 phonegap-plugins


    【解决方案1】:

    解决方案;这个插件可以转换 Base64 PNG 字符串并将图像生成到 sdCard。我们走吧!

    1. Base64 解码器

    获取这个名为 MiGBase64 的快速 Base64 编码/解码器类。从SourceForge 下载。在项目的 src/ 文件夹中创建一个名为“util”的文件夹。将下载的类放在那里。

    2。 java

    在项目的 src/ 文件夹中创建一个名为“org/apache/cordova”的文件夹。 使用以下源代码在其中创建一个名为“Base64ToPNG.java”的 Java 文件。

    package org.apache.cordova;
    
    /**
    * A phonegap plugin that converts a Base64 String to a PNG file.
    *
    * @author mcaesar
    * @lincese MIT.
    */
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    import org.apache.cordova.api.Plugin;
    import org.apache.cordova.api.PluginResult;
    import org.json.JSONArray;
    
    import android.os.Environment;
    import java.io.*;
    import org.json.JSONException;
    import org.json.JSONObject;
    import util.Base64;
    
    public class Base64ToPNG extends Plugin {
    
        @Override
        public PluginResult execute(String action, JSONArray args, String callbackId) {
    
            if (!action.equals("saveImage")) {
                return new PluginResult(PluginResult.Status.INVALID_ACTION);
            }
    
            try {
    
                String b64String = "";
                if (b64String.startsWith("data:image")) {
                    b64String = args.getString(0).substring(21);
                } else {
                    b64String = args.getString(0);
                }
                JSONObject params = args.getJSONObject(1);
    
                //Optional parameter
                String filename = params.has("filename")
                        ? params.getString("filename")
                        : "b64Image_" + System.currentTimeMillis() + ".png";
    
                String folder = params.has("folder")
                        ? params.getString("folder")
                        : Environment.getExternalStorageDirectory() + "/Pictures";
    
                Boolean overwrite = params.has("overwrite") 
                        ? params.getBoolean("overwrite") 
                        : false;
    
                return this.saveImage(b64String, filename, folder, overwrite, callbackId);
    
            } catch (JSONException e) {
    
                e.printStackTrace();
                return new PluginResult(PluginResult.Status.JSON_EXCEPTION, e.getMessage());
    
            } catch (InterruptedException e) {
                e.printStackTrace();
                return new PluginResult(PluginResult.Status.ERROR, e.getMessage());
            }
    
        }
    
        private PluginResult saveImage(String b64String, String fileName, String dirName, Boolean overwrite, String callbackId) throws InterruptedException, JSONException {
    
            try {
    
                //Directory and File
                File dir = new File(dirName);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
                File file = new File(dirName, fileName);
    
                //Avoid overwriting a file
                if (!overwrite && file.exists()) {
                    return new PluginResult(PluginResult.Status.OK, "File already exists!");
                }
    
                //Decode Base64 back to Binary format
                byte[] decodedBytes = Base64.decode(b64String.getBytes());
    
                //Save Binary file to phone
                file.createNewFile();
                FileOutputStream fOut = new FileOutputStream(file);
                fOut.write(decodedBytes);
                fOut.close();
    
    
                return new PluginResult(PluginResult.Status.OK, "Saved successfully!");
    
            } catch (FileNotFoundException e) {
                return new PluginResult(PluginResult.Status.ERROR, "File not Found!");
            } catch (IOException e) {
                return new PluginResult(PluginResult.Status.ERROR, e.getMessage());
            }
    
        }
    }
    

    3. Javascript

    将此 JavaScript 作为 Base64ToPNG.js 写入项目的 www 文件夹。不要忘记在您的 html 文件中包含对它的引用。

    /**Works on all versions prior and including Cordova 1.6.1 
    * by mcaesar
    *  MIT license
    *  
    */
    
    (function() {
        /* This increases plugin compatibility */
        var cordovaRef = window.PhoneGap || window.Cordova || window.cordova; // old to new fallbacks
    
        /**
        * The Java to JavaScript Gateway 'magic' class 
        */
        function Base64ToPNG() { }
    
        /**
        * Save the base64 String as a PNG file to the user's Photo Library
        */
        Base64ToPNG.prototype.saveImage = function(b64String, params, win, fail) {
            cordovaRef.exec(win, fail, "Base64ToPNG", "saveImage", [b64String, params]);
        };
    
        cordovaRef.addConstructor(function() {
            if (!window.plugins) {
                window.plugins = {};
            }
            if (!window.plugins.base64ToPNG) {
                window.plugins.base64ToPNG = new Base64ToPNG();
            }
        });
    
    })(); 
    

    4. plugins.xml 文件

    将以下内容添加到 res/xml/plugins.xml 文件中

    <plugin name="Base64ToPNG" value="org.apache.cordova.Base64ToPNG"/>
    

    5.最后,HTML示例和参数

    <button onclick="test();">No optional params required, Cowboy.</button> </br>
    <button onclick="test2();">Make PNG with some parameters</button>
    
    <script src="Base64ToPNG.js" type="text/javascript"></script>
    
    <script type="text/javascript">
    
    //May have a mime-type definition or not 
    var myBase64 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="//a red dot
    
    
    function test(){
    
        //Illustrates how to use plugin with no optional parameters. Just the base64 Image.
        window.plugins.base64ToPNG.saveImage(myBase64, {}, 
           function(result) {
              alert(result);
           }, function(error) {
              alert(error);
           });
     }
    
     //No mimetype definition example
     var myOtherBase64 = "iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
    
     function test2(){
    
        //Shows how to use optional parameters
        window.plugins.base64ToPNG.saveImage(myBase64, {filename:"dot.png", overwrite: true}, 
           function(result) {
              alert(result);
           }, function(error) {
              alert(error);
        });
    
     }
     </script>
    

    参数

    1. 文件名:要生成的文件的名称。默认与url中的相同。
    2. 文件夹:生成文件的目录名称。默认情况下“sdcard/图片”
    3. 覆盖:如果文件已经存在,替换它。默认为 false。

      我希望这能回答一些令人困扰的问题。编码愉快!

    【讨论】:

    • 谢谢。你为我节省了数小时来弄清楚这将如何工作!!。我做了一些小的修改来支持 mp3 文件而不是 PNG。再次感谢!!!!
    • @mcaesar 非常感谢,除了一行之外,一切都准备好了: byte[] decodedBytes = Base64.decode(b64String.getBytes());给我以下错误: Base64 类型中的方法 decode(byte[], int) 不适用于参数 (byte[]) 因为我不是 Java 专业人士,你能帮帮我吗?会很感激的。
    • 嗨@Mark。请确保您的 base64 字符串格式正确。请参阅我提供的示例。谢谢。
    • @mcaesar 得到它的工作,该行阻止我编译我的代码。我已将其更改为:byte[] decodedBytes = Base64.decode( b64String.getBytes(), Base64.DEFAULT ); 因为它需要额外的参数。我还必须删除 Javascript 中的 data:image/png;base64, 部分,因为图像已损坏,或者在插件中减去 22 个字符而不是 21 个字符。也许用任何东西替换字符串的特定部分是更可靠的选择,缺点:您必须检查每个特定的文件类型,jpg 或 png。感谢您的回复。
    • @mcaesar 我在您的代码中发现了一个错误:您检查 base64 是否以 'data:png' 开头,但在上面一行您设置 base64 = ''; :)
    【解决方案2】:

    对于任何想要将它与 kineticjs 一起使用的人,以下是一种享受:

    function saveCanvas() {
        $('#save').bind( $bind, function(){
            stage.toDataURL({
            callback: function(dataUrl){
                window.plugins.base64ToPNG.saveImage(dataUrl.substr(22,dataUrl.length), {}, 
                    function(result) {
                        alert(result);
                    }, function(error) {
                        alert(error);
                    }
                );
            },
                mimeType: 'image/png',
                quality: 0.5
            });
        });
    }
    

    【讨论】:

      【解决方案3】:

      此解决方案仅在为其提供 CLEAN Base64 字符串时才有效。 也就是说,应该去掉“data:image/png;base64”部分,否则Base64解码器填充失败,导致写入文件时出现空指针错误。

      我还注意到图片没有显示在图库中,但它已正确存储在 SD 卡上。当我把它下载到我的电脑上时,我可以很好地打开它。 不知道那是关于什么的。

      感谢您的工作!

      【讨论】:

      • 感谢您的更正。编辑 java 以支持完整的“data:image/png;base64”。至于没有出现在图库中的图片,android 仅在存储驱动器更改状态时索引媒体文件,例如从打开到关闭。
      • @mcaesar 我对您的插件有 3 个问题: 1. 我发现参数“文件夹”应该是:sdcard/somedirectory_name 而不是“somedirectory_name”。 2.我在仪器中设置了一个断点:byte[] decodedBytes = Base64.decode(b64String.getBytes());在 Base64ToPNG.java 中。我发现 Base64.decode(~) 返回一个 NULL。 3.在您的描述中,您说“将下载的类放在那里。”,但我只得到文件:Base64.java。有什么问题吗?我真的需要您的插件将我的画布转换为 .png 文件,并将其保存在本地系统中。请给我一些指导。
      • @mcaesar 您提到您更正了 java 文件以支持完整的“data:image/png;base64”,但恐怕您忘记上传编辑后的文件。谢谢你。
      • @Stallman, 1) 默认文件夹是 'Environment.getExternalStorageDirectory() + "/Pictures";'翻译为“SD卡/图片”。 2)解码器似乎工作得很好,但如果有任何问题,请参考原始代码(sourceforge.net/projects/migbase64)或获取替代解码器(codecodex.com/wiki/Encode/Decode_to/from_Base64)。 3)是的。解压后的 Base64.java 转到“src/Base64.java”。我知道这是一个长期的解决方案,但如果你一步一步地进行,它会成功的。一切顺利。
      • @mcaesar 感谢您的回复。该插件可以处理一些 base64 字符串,将其保存到本地系统中的 png 文件中。但是当字符串是 canvas.toDataURL(); 时,它就无法工作。插件有什么问题吗?或者这是我的代码的问题。
      猜你喜欢
      • 2020-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-16
      • 1970-01-01
      • 2019-09-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多