Просто мой 2с стоит:
Это основано на ответе тьюлера (в момент написания сообщения была обнаружена ошибка). Я немного изменил его, так что вот моя версия ответа tuler и mmyers (кажется, я не могу отредактировать их ответ). Я хотел попытаться сделать это немного чище и быстрее. Помимо ошибки (которую я обсуждаю в комментариях к их ответу), большая проблема, которую я имею с их версией, заключается в том, что она создает новый CountingOutputStream
при каждой записи. Это может стать очень дорогим с точки зрения памяти - тонны выделений и сборщиков мусора. Меньшая проблема заключается в том, что используется делегат, когда он может просто развернуть MultipartEntity
. Не уверенный, почему они выбрали это, таким образом я сделал это способом, с которым я был более знаком. Если кто-нибудь знает плюсы / минусы двух подходов, это было бы здорово. Наконец, метод FilterOutputStream # write (byte [], int, int) просто вызывает запись FilterOutputStream # (byte) в цикле. Документация FOS рекомендует подклассам переопределять это поведение и делать его более эффективным. Лучший способ сделать это здесь - позволить исходному OutputStream обрабатывать запрос на запись.
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
public class CountingMultiPartEntity extends MultipartEntity {
private UploadProgressListener listener_;
private CountingOutputStream outputStream_;
private OutputStream lastOutputStream_;
// the parameter is the same as the ProgressListener class in tuler's answer
public CountingMultiPartEntity(UploadProgressListener listener) {
super(HttpMultipartMode.BROWSER_COMPATIBLE);
listener_ = listener;
}
@Override
public void writeTo(OutputStream out) throws IOException {
// If we have yet to create the CountingOutputStream, or the
// OutputStream being passed in is different from the OutputStream used
// to create the current CountingOutputStream
if ((lastOutputStream_ == null) || (lastOutputStream_ != out)) {
lastOutputStream_ = out;
outputStream_ = new CountingOutputStream(out);
}
super.writeTo(outputStream_);
}
private class CountingOutputStream extends FilterOutputStream {
private long transferred = 0;
private OutputStream wrappedOutputStream_;
public CountingOutputStream(final OutputStream out) {
super(out);
wrappedOutputStream_ = out;
}
public void write(byte[] b, int off, int len) throws IOException {
wrappedOutputStream_.write(b,off,len);
++transferred;
listener_.transferred(transferred);
}
public void write(int b) throws IOException {
super.write(b);
}
}
}