Android 使用OKHTTP跟踪多部分文件上载的进度
我试图实现一个进度条来指示多部分文件上传的进度 我从对这个答案的评论中读到,我必须包装传递给RequestBody的接收器,并提供一个跟踪移动字节的回调 我已经创建了一个自定义RequestBody并用CustomSink类包装了接收器,但是通过调试,我可以看到LN44正在写入字节,并且自定义接收器写入方法只运行一次,不允许我跟踪移动的字节Android 使用OKHTTP跟踪多部分文件上载的进度,android,okhttp,okio,Android,Okhttp,Okio,我试图实现一个进度条来指示多部分文件上传的进度 我从对这个答案的评论中读到,我必须包装传递给RequestBody的接收器,并提供一个跟踪移动字节的回调 我已经创建了一个自定义RequestBody并用CustomSink类包装了接收器,但是通过调试,我可以看到LN44正在写入字节,并且自定义接收器写入方法只运行一次,不允许我跟踪移动的字节 private class CustomRequestBody extends RequestBody { MediaType conte
private class CustomRequestBody extends RequestBody {
MediaType contentType;
byte[] content;
private CustomRequestBody(final MediaType contentType, final byte[] content) {
this.contentType = contentType;
this.content = content;
}
@Override
public MediaType contentType() {
return contentType;
}
@Override
public long contentLength() {
return content.length;
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
CustomSink customSink = new CustomSink(sink);
customSink.write(content);
}
}
private class CustomSink implements BufferedSink {
private static final String TAG = "CUSTOM_SINK";
BufferedSink bufferedSink;
private CustomSink(BufferedSink bufferedSink) {
this.bufferedSink = bufferedSink;
}
@Override
public void write(Buffer source, long byteCount) throws IOException {
Log.d(TAG, "source size: " + source.size() + " bytecount" + byteCount);
bufferedSink.write(source, byteCount);
}
@Override
public void flush() throws IOException {
bufferedSink.flush();
}
@Override
public Timeout timeout() {
return bufferedSink.timeout();
}
@Override
public void close() throws IOException {
bufferedSink.close();
}
@Override
public Buffer buffer() {
return bufferedSink.buffer();
}
@Override
public BufferedSink write(ByteString byteString) throws IOException {
return bufferedSink.write(byteString);
}
@Override
public BufferedSink write(byte[] source) throws IOException {
return bufferedSink.write(source);
}
@Override
public BufferedSink write(byte[] source, int offset, int byteCount) throws IOException {
return bufferedSink.write(source, offset, byteCount);
}
@Override
public long writeAll(Source source) throws IOException {
return bufferedSink.writeAll(source);
}
@Override
public BufferedSink writeUtf8(String string) throws IOException {
return bufferedSink.writeUtf8(string);
}
@Override
public BufferedSink writeString(String string, Charset charset) throws IOException {
return bufferedSink.writeString(string, charset);
}
@Override
public BufferedSink writeByte(int b) throws IOException {
return bufferedSink.writeByte(b);
}
@Override
public BufferedSink writeShort(int s) throws IOException {
return bufferedSink.writeShort(s);
}
@Override
public BufferedSink writeShortLe(int s) throws IOException {
return bufferedSink.writeShortLe(s);
}
@Override
public BufferedSink writeInt(int i) throws IOException {
return bufferedSink.writeInt(i);
}
@Override
public BufferedSink writeIntLe(int i) throws IOException {
return bufferedSink.writeIntLe(i);
}
@Override
public BufferedSink writeLong(long v) throws IOException {
return bufferedSink.writeLong(v);
}
@Override
public BufferedSink writeLongLe(long v) throws IOException {
return bufferedSink.writeLongLe(v);
}
@Override
public BufferedSink emitCompleteSegments() throws IOException {
return bufferedSink.emitCompleteSegments();
}
@Override
public OutputStream outputStream() {
return bufferedSink.outputStream();
}
}
有谁能举个例子说明我将如何着手做这件事吗?- 我们只需要创建一个定制的
,不需要实现定制的RequestBody
。我们可以分配Okio缓冲区来读取图像文件,并将该缓冲区连接到接收器BufferedSink
createCustomRequestBody
函数
public static RequestBody createCustomRequestBody(final MediaType contentType, final File file) {
return new RequestBody() {
@Override public MediaType contentType() {
return contentType;
}
@Override public long contentLength() {
return file.length();
}
@Override public void writeTo(BufferedSink sink) throws IOException {
Source source = null;
try {
source = Okio.source(file);
//sink.writeAll(source);
Buffer buf = new Buffer();
Long remaining = contentLength();
for (long readCount; (readCount = source.read(buf, 2048)) != -1; ) {
sink.write(buf, readCount);
Log.d(TAG, "source size: " + contentLength() + " remaining bytes: " + (remaining -= readCount));
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
}
- 使用-
.addPart( Headers.of("Content-Disposition", "form-data; name=\"image\""), createCustomRequestBody(MediaType.parse("image/png"), new File("test.jpg"))) .build()
您可以找到一个完整的实现,它支持在AdapterView中显示进度,还可以根据我的要点取消上载:这件事非常有效 格拉德尔
dependencies {
compile 'io.github.lizhangqu:coreprogress:1.0.2'
}
//wrap your original request body with progress
RequestBody requestBody = ProgressHelper.withProgress(body, new ProgressUIListener()....}
这里有完整的示例代码
如果通过缓慢的网络连接上载小文件,则这似乎不起作用。看见有没有解决这个问题的方法?@Edy Bolos有没有办法将它与RxJava&Observable结合使用?回答你的问题:一切都可以包装在Observable中:),但我必须让其他人来做。我唯一的建议是使用
BehaviorSubject
在UploadsHandler
中发出进度值,正如前面的评论员所说的那样。即使在连接不好的情况下,小文件也不会取得进展。这是关于网络接口发送缓冲区如此之高,以至于吞没了整个文件,okHttp将报告它100%上传。使用此选项可以修复此问题。你们能定义一下你们所说的“小”是指10MB还是2MB,或者是什么…?这不会像预期的那样起作用,原因在文章中解释在每个段之后刷新接收器非常重要,否则进度条将很快填满,而文件不会通过网络实际发送
dependencies {
compile 'io.github.lizhangqu:coreprogress:1.0.2'
}
//wrap your original request body with progress
RequestBody requestBody = ProgressHelper.withProgress(body, new ProgressUIListener()....}