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

时间:2018-02-02 18:02:16

标签: android python sockets tcp base64

在我正在构建的Android应用程序中,我使用Base64.encodeToString()将jpg图像转换为字符串,并通过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代码,它接收消息并尝试将其解码为image:

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 个答案:

答案 0 :(得分:0)

    msg = con.recv(1024000) #Initially 1024 but changet so the message

这将从套接字读取最多 1024000字节。它可能不会这样。并且,使用recv读取的块的大小不需要与对等方写入的块的大小有任何关联,除了读取所有recv的总大小与总大小相匹配发送。

    file.write(base64.decodestring(msg))

base64字符串的大小始终是4个字节的倍数。即使解码数据只是一个字节,编码字符串也将是4个字节:2编码输入,2&#39; =&#39;用于填充。如果与decodestring一起使用的字符串长度不是4的倍数,则会假设填充不良,即提升binascii.Error: Incorrect padding

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

答案 1 :(得分:0)

我在做和你说的完全一样的事情。

  

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

我终于明白了。

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

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

如果要检查我的工作方式,这是我的项目: Android side Python side