通过Python使用套接字从Android手机向PC发送图像文件

huangapple go评论156阅读模式
英文:

Sending an image file from an Android phone to a PC through Python using sockets

问题

public void send(View v) {
    Intent i = new Intent(Intent.ACTION_OPEN_DOCUMENT);
    i.addCategory(Intent.CATEGORY_OPENABLE);
    i.setType("image/*");
    startActivityForResult(i, 1);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    if (requestCode == 1 && resultCode == RESULT_OK) {

        try {
            final Uri imageUri = data.getData();
            final InputStream imageStream = getContentResolver().openInputStream(imageUri);
            final Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);
            imageView.setImageBitmap(selectedImage);

            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            selectedImage.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
            byte[] array = byteArrayOutputStream.toByteArray();

            SendImageClient sendImageClient = new SendImageClient();
            sendImageClient.execute(array);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

    } else {
        Toast.makeText(this, "no image selected", Toast.LENGTH_SHORT).show();
    }

}


public class SendImageClient extends AsyncTask<byte[], Void, Void> {


    @Override
    protected Void doInBackground(byte[]... voids) {

        try {
            Socket socket= new Socket("192.168.0.106",8888);

            OutputStream out=socket.getOutputStream();
            DataOutputStream dataOutputStream=new DataOutputStream(out);
            dataOutputStream.writeInt(voids[0].length);
            dataOutputStream.write(voids[0],0,voids[0].length);
            handler.post(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(MainActivity.this, "Image sent", Toast.LENGTH_SHORT).show();
                }
            });

            dataOutputStream.close();
            out.close();
            socket.close();

        } catch (IOException e) {
            e.printStackTrace();
        }


        return null;
    }
}
英文:

I want to send an image from my android device to python through sockets, I've been successful in sending text from Android-Python.
When I send the image I get the toast of the image being sent but on the receiving end the image is corrupted with a 0 KB size
I appreciate any help, as I'm currently stuck here.

Here is my code

image.py

from socket import *
port = 8888
s = socket(AF_INET, SOCK_STREAM)
s.bind((&#39;&#39;, port))
s.listen(1) #listens to 1 connection
conn, addr = s.accept()
print(&quot;Connected by the &quot;,addr)
while True:
data = conn.recv(1024)
with open(&#39;image.jpg&#39;, &#39;wb&#39;) as file:
file.write(data)
conn.close() 

The Android side code is,

public void send(View v) {
Intent i = new Intent(Intent.ACTION_OPEN_DOCUMENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType(&quot;image/*&quot;);
startActivityForResult(i, 1);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (requestCode == 1 &amp;&amp; resultCode == RESULT_OK) {
try {
final Uri imageUri = data.getData();
final InputStream imageStream = getContentResolver().openInputStream(imageUri); 
final Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);
imageView.setImageBitmap(selectedImage);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
selectedImage.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
byte[] array = byteArrayOutputStream.toByteArray();
SendImageClient sendImageClient = new SendImageClient();
sendImageClient.execute(array);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
} else {
Toast.makeText(this, &quot;no image selected&quot;, Toast.LENGTH_SHORT).show();
}
}
public class SendImageClient extends AsyncTask&lt;byte[], Void, Void&gt; {
@Override
protected Void doInBackground(byte[]... voids) {
try {
Socket socket= new Socket(&quot;192.168.0.106&quot;,8888);
OutputStream out=socket.getOutputStream();
DataOutputStream dataOutputStream=new DataOutputStream(out);
dataOutputStream.writeInt(voids[0].length);
dataOutputStream.write(voids[0],0,voids[0].length);
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, &quot;Image sent&quot;, Toast.LENGTH_SHORT).show();
}
});
dataOutputStream.close();
out.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}

答案1

得分: 0

你的Python代码在每次循环运行时都会截断输出文件。在最后一次运行时,当连接关闭时,文件会被截断,conn.recv 将返回一个空字符串,并且不会将其他任何内容写入文件。

with open(..) 移出从套接字读取的循环,并处理连接关闭,以便避免无限循环:

with open('image.jpg', 'wb') as file:
    while True:
        data = conn.recv(1024)
        if not data: break
        file.write(data)

你的Java代码在发送实际数据之前会先发送数据的大小 - 你应该要么删除这部分,要么调整Python代码以考虑这一点。

dataOutputStream.writeInt(voids[0].length);
dataOutputStream.write(voids[0], 0, voids[0].length);
英文:

Your python code is truncating the output file on every run of the loop. On the last run, when the connection is closed, the file is truncated, conn.recv will return an empty string, and nothing else will be written to the file.

Move with open(..) outside the loop that reads from the socket, and handle the connection closing so you don't have an infinite loop:

with open(&#39;image.jpg&#39;, &#39;wb&#39;) as file:
while True:
data = conn.recv(1024)
if not data: break
file.write(data)

Your java code is sending the size of the data it's sending before the data itself - you should either remove this or adjust the python code to take this into account.

            dataOutputStream.writeInt(voids[0].length);
dataOutputStream.write(voids[0],0,voids[0].length);

huangapple
  • 本文由 发表于 2020年4月5日 20:59:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/61042985.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定