使用 POST 和 HttpURLConnection 发送文件 [英] Sending files using POST with HttpURLConnection
问题描述
由于 Android 开发者建议使用HttpURLConnection
类,我想知道是否有人可以为我提供一个很好的示例,说明如何通过 POST 将位图文件"(实际上是内存中的流)发送到 Apache HTTP 服务器.我对 cookie 或身份验证或任何复杂的东西不感兴趣,但我只想有一个可靠的逻辑实现.我在这里看到的所有例子看起来更像是让我们试试这个,也许它会奏效".
Since the Android developers recommend to use the HttpURLConnection
class, I was wondering if anyone can provide me with a good example on how to send a bitmap "file" (actually an in-memory stream) via POST to an Apache HTTP server. I'm not interested in cookies or authentication or anything complicated, but I just want to have a reliable and logic implementation. All the examples that I've seen around here look more like "let's try this and maybe it works".
现在,我有这个代码:
URL url;
HttpURLConnection urlConnection = null;
try {
url = new URL("http://example.com/server.cgi");
urlConnection = (HttpURLConnection) url.openConnection();
} catch (Exception e) {
this.showDialog(getApplicationContext(), e.getMessage());
}
finally {
if (urlConnection != null)
{
urlConnection.disconnect();
}
}
showDialog 应该在哪里显示 AlertDialog
(如果 URL 无效?).
where showDialog should just display an AlertDialog
(in case of an invalid URL?).
现在,假设我生成了一个像这样的位图:Bitmap image = this.getBitmap()
在从 View
派生的控件中,我想通过邮政.实现这一目标的正确程序是什么?我需要使用哪些类?我可以像这个例子那样使用HttpPost
吗?如果是这样,我将如何为我的位图构造 InputStreamEntity
?我会发现要求首先将位图存储在设备上的文件中是令人反感的.
Now, let's say that I generate a bitmap like so: Bitmap image = this.getBitmap()
inside a control derived from View
and I want to send it via POST. What would be the proper procedure to achieve such a thing? What classes do I need to use? Can I use HttpPost
like in this example? If so, how would I construct the InputStreamEntity
for my bitmap? I would find it revolting to be required to first store the bitmap in a file on the device.
我还要提一下,我真的需要将原始位图的每个未更改像素发送到服务器,因此我无法将其转换为 JPEG.
I should also mention that I really need to send every unaltered pixel of the original bitmap to the server, so I can't convert it to JPEG.
推荐答案
我不知道为什么 HttpURLConnection
类不提供任何发送文件的方法,而无需手动编写文件包装器.这是我最终做的,但如果有人知道更好的解决方案,请告诉我.
I have no idea why the HttpURLConnection
class does not provide any means to send files without having to compose the file wrapper manually. Here's what I ended up doing, but if someone knows a better solution, please let me know.
输入数据:
Bitmap bitmap = myView.getBitmap();
静态内容:
String attachmentName = "bitmap";
String attachmentFileName = "bitmap.bmp";
String crlf = "
";
String twoHyphens = "--";
String boundary = "*****";
设置请求:
HttpURLConnection httpUrlConnection = null;
URL url = new URL("http://example.com/server.cgi");
httpUrlConnection = (HttpURLConnection) url.openConnection();
httpUrlConnection.setUseCaches(false);
httpUrlConnection.setDoOutput(true);
httpUrlConnection.setRequestMethod("POST");
httpUrlConnection.setRequestProperty("Connection", "Keep-Alive");
httpUrlConnection.setRequestProperty("Cache-Control", "no-cache");
httpUrlConnection.setRequestProperty(
"Content-Type", "multipart/form-data;boundary=" + this.boundary);
启动内容包装器:
DataOutputStream request = new DataOutputStream(
httpUrlConnection.getOutputStream());
request.writeBytes(this.twoHyphens + this.boundary + this.crlf);
request.writeBytes("Content-Disposition: form-data; name="" +
this.attachmentName + "";filename="" +
this.attachmentFileName + """ + this.crlf);
request.writeBytes(this.crlf);
将 Bitmap
转换为 ByteBuffer
:
//I want to send only 8 bit black & white bitmaps
byte[] pixels = new byte[bitmap.getWidth() * bitmap.getHeight()];
for (int i = 0; i < bitmap.getWidth(); ++i) {
for (int j = 0; j < bitmap.getHeight(); ++j) {
//we're interested only in the MSB of the first byte,
//since the other 3 bytes are identical for B&W images
pixels[i + j] = (byte) ((bitmap.getPixel(i, j) & 0x80) >> 7);
}
}
request.write(pixels);
结束内容包装器:
request.writeBytes(this.crlf);
request.writeBytes(this.twoHyphens + this.boundary +
this.twoHyphens + this.crlf);
刷新输出缓冲区:
request.flush();
request.close();
获取回复:
InputStream responseStream = new
BufferedInputStream(httpUrlConnection.getInputStream());
BufferedReader responseStreamReader =
new BufferedReader(new InputStreamReader(responseStream));
String line = "";
StringBuilder stringBuilder = new StringBuilder();
while ((line = responseStreamReader.readLine()) != null) {
stringBuilder.append(line).append("
");
}
responseStreamReader.close();
String response = stringBuilder.toString();
关闭响应流:
responseStream.close();
关闭连接:
httpUrlConnection.disconnect();
PS:当然我不得不把请求包裹在private class AsyncUploadBitmaps extends AsyncTask
,为了让Android平台开心,因为它不喜欢在主线程上有网络请求.
PS: Of course I had to wrap the request in private class AsyncUploadBitmaps extends AsyncTask<Bitmap, Void, String>
, in order to make the Android platform happy, because it doesn't like to have network requests on the main thread.
这篇关于使用 POST 和 HttpURLConnection 发送文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!