AndroidからHTTPのmultipart/form-dataを使ってデータをアップロードする

  • 23
    Like
  • 0
    Comment
More than 1 year has passed since last update.

AndroidのHTTP Clientとしてはorg.apache.httpにあるライブラリ群とjava.net.HttpURLConnectionがあるが,org.apache.httpは推奨されていない.さらにmultipart/form-dataを使ってファイルをアップロードするにはクラスがいくつか足らない.そこで,java.net.HttpURLConnectionを使ってファイルをアップロードする簡単なライブラリを書いてみた.コードはAndroid snippetsを参考に実装した.私の改変部分はMITライセンスでどうぞ.もとのAndroid SnippetsのコードはPublic Domainです.

package info.informationsea.apps;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.util.Map;
import java.util.UUID;

/**
 * Copyright (C) 2014 Yasunobu OKAMURA
 * MIT License
 */
public class HttpMultipartSender {
    private HttpMultipartSender(){} // cannot make instance

    // this function is implemented based on http://www.androidsnippets.com/multipart-http-requests
    public static void sendMultipart(HttpURLConnection connection, String filefield, File filepath, Map<String, String> textdata) throws IOException {

        final String twoHyphens = "--";
        final String boundary =  "*****"+ UUID.randomUUID().toString()+"*****";
        final String lineEnd = "\r\n";
        final int maxBufferSize = 1024*1024*3;

        DataOutputStream outputStream;

        connection.setDoInput(true);
        connection.setDoOutput(true);
        connection.setUseCaches(false);

        connection.setRequestMethod("POST");
        connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setRequestProperty("Content-Type", "multipart/form-data; boundary="+boundary);

        outputStream = new DataOutputStream(connection.getOutputStream());
        outputStream.writeBytes(twoHyphens + boundary + lineEnd);
        outputStream.writeBytes("Content-Disposition: form-data; name=\"" + filefield + "\"; filename=\"" + filepath.getName() +"\"" + lineEnd);
        outputStream.writeBytes("Content-Type: application/octet-stream" + lineEnd);
        outputStream.writeBytes("Content-Transfer-Encoding: binary" + lineEnd);
        outputStream.writeBytes(lineEnd);

        FileInputStream fileInputStream = new FileInputStream(filepath);
        int bytesAvailable = fileInputStream.available();
        int bufferSize = Math.min(bytesAvailable, maxBufferSize);
        byte[] buffer = new byte[bufferSize];

        int bytesRead = fileInputStream.read(buffer, 0, bufferSize);
        while(bytesRead > 0) {
            outputStream.write(buffer, 0, bufferSize);
            bytesAvailable = fileInputStream.available();
            bufferSize = Math.min(bytesAvailable, maxBufferSize);
            bytesRead = fileInputStream.read(buffer, 0, bufferSize);
        }

        outputStream.writeBytes(lineEnd);

        for (Map.Entry<String, String> entry : textdata.entrySet()) {
            outputStream.writeBytes(twoHyphens + boundary + lineEnd);
            outputStream.writeBytes("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + lineEnd);
            outputStream.writeBytes("Content-Type: text/plain"+lineEnd);
            outputStream.writeBytes(lineEnd);
            outputStream.writeBytes(entry.getValue());
            outputStream.writeBytes(lineEnd);
        }

        outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

        outputStream.close();
    }
}