Ham*_*eni 5 android file-upload okhttp3
我正在尝试使用OkHttp跟踪上传的进度.我创建了一个RequestBody带有以下主体的自定义(由此答案提供),它写入接收器并发布进度.
public class CountingFileRequestBody extends RequestBody {
private static final String TAG = "CountingFileRequestBody";
private final ProgressListener listener;
private final String key;
private final MultipartBody multipartBody;
protected CountingSink mCountingSink;
public CountingFileRequestBody(MultipartBody multipartBody,
String key,
ProgressListener listener) {
this.multipartBody = multipartBody;
this.listener = listener;
this.key = key;
}
@Override
public long contentLength() throws IOException {
return multipartBody.contentLength();
}
@Override
public MediaType contentType() {
return multipartBody.contentType();
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
mCountingSink = new CountingSink(sink);
BufferedSink bufferedSink = Okio.buffer(mCountingSink);
multipartBody.writeTo(bufferedSink);
bufferedSink.flush();
}
public interface ProgressListener {
void transferred(String key, int num);
}
protected final class CountingSink extends ForwardingSink {
private long bytesWritten = 0;
public CountingSink(Sink delegate) {
super(delegate);
}
@Override
public void write(Buffer source, long byteCount) throws IOException {
bytesWritten += byteCount;
listener.transferred(key, (int) (100F * bytesWritten / contentLength()));
super.write(source, byteCount);
delegate().flush(); // I have added this line to manually flush the sink
}
}
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是,接收器被写入以立即接收,而不实际将缓冲的字节发送到服务器.这意味着我的进度在实际上传之前很久就会结束.
注意: 有些人认为接收器需要在每次迭代时刷新,以便实际上传字节,但它对我不起作用.
我知道这是一篇旧文章,但对于有同样问题的人,我从这个库改编了一个帮助器类(ProgressOutputStream):https: //github.com/lizhangqu/CoreProgress,我的工作代码如下:(为上传文件以及上传 json)
import java.io.IOException;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.BufferedSink;
import okio.Okio;
public class UploadProgressRequestBody extends RequestBody {
private final RequestBody requestBody;
private final ProgressListener progressListener;
public UploadProgressRequestBody(RequestBody requestBody) {
this.requestBody = requestBody;
this.progressListener = getDefaultProgressListener();
}
@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 {
if (progressListener == null) {
requestBody.writeTo(sink);
return;
}
ProgressOutputStream progressOutputStream = new ProgressOutputStream(sink.outputStream(), progressListener, contentLength());
BufferedSink progressSink = Okio.buffer(Okio.sink(progressOutputStream));
requestBody.writeTo(progressSink);
progressSink.flush();
}
interface ProgressListener {
void update(long bytesWritten, long contentLength);
}
private ProgressListener getDefaultProgressListener(){
ProgressListener progressListener = new UploadProgressRequestBody.ProgressListener() {
@Override public void update(long bytesRead, long contentLength) {
System.out.println("bytesRead: "+bytesRead);
System.out.println("contentLength: "+contentLength);
System.out.format("%d%% done\n", (100 * bytesRead) / contentLength);
}
};
return progressListener;
}
}
Run Code Online (Sandbox Code Playgroud)
===========
import java.io.IOException;
import java.io.OutputStream;
class ProgressOutputStream extends OutputStream {
private final OutputStream stream;
private final UploadProgressRequestBody.ProgressListener listener;
private long total;
private long totalWritten;
ProgressOutputStream(OutputStream stream, UploadProgressRequestBody.ProgressListener listener, long total) {
this.stream = stream;
this.listener = listener;
this.total = total;
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
this.stream.write(b, off, len);
if (this.total < 0) {
this.listener.update(-1, -1);
return;
}
if (len < b.length) {
this.totalWritten += len;
} else {
this.totalWritten += b.length;
}
this.listener.update(this.totalWritten, this.total);
}
@Override
public void write(int b) throws IOException {
this.stream.write(b);
if (this.total < 0) {
this.listener.update(-1, -1);
return;
}
this.totalWritten++;
this.listener.update(this.totalWritten, this.total);
}
@Override
public void close() throws IOException {
if (this.stream != null) {
this.stream.close();
}
}
@Override
public void flush() throws IOException {
if (this.stream != null) {
this.stream.flush();
}
}
}
Run Code Online (Sandbox Code Playgroud)
=========
OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(new Interceptor() {
@Override public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
if (originalRequest.body() == null) {
return chain.proceed(originalRequest);
}
Request progressRequest = originalRequest.newBuilder()
.method(originalRequest.method(),
new UploadProgressRequestBody(originalRequest.body()))
.build();
return chain.proceed(progressRequest);
}
}).build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
747 次 |
| 最近记录: |