我尝试使用OkHttp跟踪上传的进度。我创建了一个自定义class Pet: NSObject {
var name : String?
var birthYear : String?
var birthMonth : String?
var gender : String?
var breed : String?
}
,其中包含以下正文(由this answer提供),该正文写入接收器并发布进度。
RequestBody
这里的问题是,接收器被写入以立即接收,而不实际将缓冲的字节发送到服务器。这意味着我的进度在实际上传之前很久就会结束 注意: Some say接收器需要在每次迭代时刷新,以便实际上传字节,但它对我不起作用。
答案 0 :(得分:1)
我知道这是一篇旧帖子,但对于有同样问题的人,我从这个lib中调整了一个帮助类(ProgressOutputStream):https://github.com/lizhangqu/CoreProgress我的工作代码如下:(用于上传文件和也可以上传json)
{
"data":{
"fieldA":"A",
"fieldB" : "B",
"fieldC" : "C",
"total" : 1234,
"title" : "_my_title",
"message" : "_my_message",
"sound" : "default",
"cick_action": "FCM_PLUGIN_ACTIVITY"
},
"to":"/topics/MY_TOPIC",
"priority":"high"
}
===========
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;
}
}
==========
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();
}
}
}
答案 1 :(得分:1)
经过辛苦的一天的挖掘,我发现了这个天才的解决方案,可以在网络接口级别设置缓冲区大小。我的问题是进度正在立即(眨眼)跳到一半以上。原来,正在读取我的输入流,并且正在写入缓冲区(输出流),直到系统确定足够,消耗掉它然后继续进行操作。这使得无法准确跟踪上载进度。看一看: Fix for upload progress monitoring in Android.
尝试该类,并将其sendBufferSize设置为较小但合理的值或证明合适的值。
int sendBufferSize = 128 * 1028;
new OkHttpClient.Builder().socketFactory(new RestrictedSocketFactory(sendBufferSize));
关于进度跃升至100的问题的注释:我遇到了很多答案,表明这是由于OkHttp日志记录所致。尝试将其关闭,看看是否有帮助。