代码之家  ›  专栏  ›  技术社区  ›  Mateus Arruda

无法使用Base64将字符串解码为图像

  •  1
  • Mateus Arruda  · 技术社区  · 7 年前

    在我正在构建的android应用程序中,我使用Base64将jpg图像转换为字符串。encodeToString()并通过TCP套接字发送到服务器。

    问题是当我尝试将字符串解码回图像时。 我可以打印我收到的字符串,它在文件末尾看起来是这样的(我唯一可以复制的部分,因为文件太大,无法在终端上打印所有内容):

    ....+77DgjRKHqbxBmYCDOzv9vLzFwff4N146snCWin6ZlzbN++HJOIIPodB/JTOoc1NjczeqoHwOju
    iWdI6ePeSO0ADz46vh4LODnM7FCJYhbTX0TizmNatXvxSFoVzLiqfn19iYjvAPD/AQnRoUxtpJij
    AAAAAElFTkSuQmCC
    

    但当我再次尝试解码并保存到jpg文件时,我得到以下错误:

    Traceback (most recent call last):
      File "tcp.py", line 20, in <module>
        file.write(base64.decodestring(msg))
      File "/usr/lib/python2.7/base64.py", line 328, in decodestring
        return binascii.a2b_base64(s)
    binascii.Error: Incorrect padding
    

    下面是我的一段Android应用程序代码,用于编码和发送消息:

    //Function that encodes the Bitmapfile into string
        public String BitMapToString(Bitmap bitmap){
            ByteArrayOutputStream baos=new  ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.PNG,100, baos);
            byte [] arr=baos.toByteArray();
            String result=Base64.encodeToString(arr, Base64.DEFAULT);
            return result;
        }
    
        class myTask extends AsyncTask<Void,Void,Void>
        {
            //Faz a conexao entre aparelho e servidor
            @Override
            protected Void doInBackground(Void... params){
    
                try
                {
                    //create socket and buffer to send the string message
                    newSocket = new Socket(ipAdress,5000);
                    printWriter = new PrintWriter(newSocket.getOutputStream());
                    bufferedWriter = new BufferedWriter(new OutputStreamWriter(newSocket.getOutputStream()));
    
                    //Reads the internal storage image and converts into string using Base64
                    File file  = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM+"/Reccoon3D/123.jpg");
                    Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
                    message = BitMapToString(bitmap); //encodes the bitmap
                    //sends the enconded image
                    bufferedWriter.write(message);
                    bufferedWriter.flush();
                    bufferedWriter.close();
                    newSocket.close();
                }catch (Exception e)
                {
                    e.printStackTrace();
                }
                return null;
            }
        }
    

    下面是我的python代码,它接收消息并尝试再次将其解码为图像:

    import socket
    import base64 
    
    host = '192.168.1.16'
    port = 5000
    tcp=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    orig = (host,port)
    tcp.bind(orig)
    tcp.listen(1)
    file=open('file.png','wb')
    
    while True:
        con, client = tcp.accept()
        print('Conected by', client)
        while True:
            msg = con.recv(1024000) #Initially 1024 but changet so the message
                                    #would not be sliced into pieces
            if not msg: break
            #print(msg)
            file.write(base64.decodestring(msg))
    
        print('Finalizado com sucesso')
        con.close
    
    2 回复  |  直到 7 年前
        1
  •  0
  •   Steffen Ullrich    7 年前
        msg = con.recv(1024000) #Initially 1024 but changet so the message
    

    这将显示 高达 来自套接字的1024000字节。可能会比这少。并且,使用 recv 除了读取的总大小之外,不需要与对等方编写的块的大小有任何关联 recv公司 匹配发送的总大小。

        file.write(base64.decodestring(msg))
    

    base64字符串的大小始终是4字节的倍数。即使解码数据只有一个字节,编码字符串也将是4个字节:2个字节用于编码输入,2个“=”用于填充。如果使用的字符串长度 decodestring 不是4的倍数,它将假定填充错误,即raise binascii.Error: Incorrect padding .

    您的代码盲目地假设 msg 将始终是4的倍数,因为您假定 recv公司 将返回发送的所有数据。但是,这个假设是错误的,如果 消息 不是4的倍数,您会看到错误。

        2
  •  0
  •   Antonio Davila    5 年前

    我做的和你说的完全一样。

    在我正在构建的android应用程序中,我将jpg图像转换为 使用Base64的字符串。encodeToString()并通过TCP发送到服务器 插座

    我终于明白了。

    首先我用作模板 this 项目在这里,您可以拍摄快照,然后将其加载为位图。然后必须将其转换为编码为PNG文件的字节数组,然后通过base64算法(已经在Java中实现)对其进行编码。

    然后,我用python和其他一些东西制作了一个套接字服务器来处理传输。获得编码字符串后,只需对其进行解码并将结果字符串保存为。然后加载png文件 cv2.imread() 还有Vuala!

    如果您想查看我是如何完成的,以下是我的项目: Android side Python side