我正在尝试使用okhttp3库上传图像。
当上传开始时,okhttp会占用所有可用带宽,因此无法与我的应用或任何其他应用建立任何其他连接。
我的代码是:
ProgressRequestBody fileBody = new ProgressRequestBody(
RequestBody.create(MediaType.parse(getMimeType(sourceFile)), sourceFile),
new ProgressRequestBody.Listener() {
@Override
public void onProgress(int progress) {
//update progress
}
});
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("key", key)
.addFormDataPart("file", sourceFile.getName(), fileBody)
.build();
Request request = new Request.Builder()
.url(Global.server_url + "upload")
.addHeader("authorization", Global.g_userInfo.getSessionId())
.post(requestBody)
.build();
Response response = okHttpClient.newCall(request).execute();
responseString = response.body().string();
statusCode = response.code();
答案 0 :(得分:1)
您可以限制正在读取的缓冲区的速度。 例如,每上传24KB数据,我们就会休眠100ms。
这可以使用以下自定义ProgressRequestBody实现:
public class ProgressRequestBody extends RequestBody {
protected final RequestBody requestBody;
protected final OnProgressListener listener;
protected ProgressForwardingSink progressForwardingSink;
public ProgressRequestBody(RequestBody requestBody, OnProgressListener listener) {
this.requestBody = requestBody;
this.listener = listener;
Timber.d("Throttle upload by adding %dms delay every %dKB", CHUNCK_DELAY, CHUNK_SIZE/1024);
}
@Override
public MediaType contentType() {
return requestBody.contentType();
}
@Override
public long contentLength() {
try {
return requestBody.contentLength();
} catch (IOException e) {
e.printStackTrace();
}
return -1;
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
progressForwardingSink = new ProgressForwardingSink(sink);
BufferedSink bufferedSink = Okio.buffer(progressForwardingSink);
requestBody.writeTo(bufferedSink);
bufferedSink.flush();
}
protected final class ProgressForwardingSink extends ForwardingSink {
public final static int CHUNK_SIZE = 24 * 1024; // progress is updated every 8KB
public final static long CHUNCK_DELAY = 100;
private long bytesWritten = 0;
private long lastIndex = 0;
public ProgressForwardingSink(Sink delegate) {
super(delegate);
}
@Override
public void write(Buffer source, long byteCount) throws IOException {
super.write(source, byteCount);
bytesWritten += byteCount;
long index = bytesWritten / CHUNK_SIZE;
Timber.d("bytesWritten %d index: %d lastIndex: %d", bytesWritten, index, lastIndex);
if (index > lastIndex) {
lastIndex = index;
try {
Timber.d("sleep %dms", CHUNCK_DELAY);
Thread.sleep(CHUNCK_DELAY);
} catch (InterruptedException e) {
Timber.d("chunk sleep interrupted");
}
}
listener.onRequestProgress(bytesWritten, contentLength());
}
}
public interface OnProgressListener {
void onRequestProgress(long bytesWritten, long contentLength);
}
}
像这样将ProgressRequestBody附加到您的请求:
ProgressRequestBody progressRequestBody = new ProgressRequestBody(requestBody, (bytesWritten, contentLength) -> {
int percent = Math.round(100 * ((float) bytesWritten) / ((float) contentLength));
Timber.d("upload progress: %d/%d %d%%", bytesWritten, contentLength, percent);
});
Request request = new Request.Builder()
.url(Global.server_url + "upload")
.addHeader("authorization", Global.g_userInfo.getSessionId())
.post(progressRequestBody)
.build();