1. ホーム
  2. android

[解決済み] HttpURLConnectionを使ったPOSTによるファイル送信

2022-07-21 07:55:19

質問

Androidの開発者は をお勧めします。 を使用することを推奨しています。 HttpURLConnection クラスで、ビットマップの "file" (実際にはメモリ内のストリーム) を Apache HTTP サーバに POST で送信する方法について、誰かが良い例を提供できるかどうか疑問に思っています。クッキーや認証など複雑なものには興味がないのですが、ただ信頼できるロジック実装が欲しいのです。私がこのあたりで見たすべての例は、「これを試してみて、たぶんうまくいくだろう」というように見えます。

今、私はこのコードを持っています。

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の場合?)

さて、このようにビットマップを生成するとします。 Bitmap image = this.getBitmap() から派生したコントロールの内部で View から派生したコントロールの中にあり、それをPOSTで送信したいのです。このようなことを実現するには、どのような手順が適切でしょうか?どのようなクラスを使用する必要がありますか?私は HttpPost のように この例では ? もしそうなら、どのように InputStreamEntity をどのように構築すればよいのでしょうか? 最初にビットマップをデバイス上のファイルに保存することを要求されるのは、不愉快だと思います。


私は本当にオリジナルのビットマップのすべての変更されていないピクセルをサーバーに送信する必要があるので、JPEG に変換することができないことも述べておかなければなりません。

どのように解決するのですか?

私はなぜ HttpURLConnection クラスが、手動でファイルラッパーを構成することなくファイルを送信する手段を提供しないのか、全く理解できません。以下は私が最終的に行ったことですが、もし誰かがより良い解決策を知っているならば、教えてください。

入力データです。

Bitmap bitmap = myView.getBitmap();

静的なもの

String attachmentName = "bitmap";
String attachmentFileName = "bitmap.bmp";
String crlf = "\r\n";
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);

変換する BitmapByteBuffer :

//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("\n");
}
responseStreamReader.close();

String response = stringBuilder.toString();

レスポンスストリームを閉じる。

responseStream.close();

接続を閉じます。

httpUrlConnection.disconnect();

PS: もちろん、リクエストを private class AsyncUploadBitmaps extends AsyncTask<Bitmap, Void, String> これは Android プラットフォームがメインスレッドでネットワークリクエストを持つことを好まないからです。