HttpComponentsを使ってマルチパート・フォームデータとしてファイルをサーバに送信する際にファイルのアップロードの進捗をUIに反映させたい、ということがあって調べてみるも、公式なやり方を見つけられなかった。
それで実際にアップロード処理を実行しているところを探すとファイルデータのパートを扱うオブジェクトのwriteToメソッドがその場所だったので、これをオーバーライドすればよさそうだということで、下のようなクラスを作った。
import org.apache.http.entity.mime.content.InputStreamBody; public class ObservableFileStreamBody extends InputStreamBody { public interface ProgressListener { public void updateProgress(long written, long total); } private ProgressListener listener; private long total; public ObservableFileStreamBody(File file, String mimeType, String filename) throws FileNotFoundException { super(new FileInputStream(file), mimeType, filename); total = file.length(); } public void setProgressListener(ProgressListener l) { listener = l; } @Override public void writeTo(OutputStream out) throws IOException { if (out == null) { throw new IllegalArgumentException("Output stream may not be null"); } InputStream in = getInputStream(); try { byte[] tmp = new byte[4096]; int len; long sum = 0; while ((len = in.read(tmp)) != -1) { out.write(tmp, 0, len); if (listener != null) { sum += len; listener.updateProgress(sum, total); } } out.flush(); } finally { in.close(); } } }
FileBodyではなくInputStreamBodyを継承しているのはファイル名を明示的に指定する必要が個人的にあったからです。