Hier erfahren Sie, wie Sie den Fortschritt der Upload-Datei mit einem einfachen POST anstelle von Multipart behandeln. Weitere Informationen finden Sie in der Lösung von @ Yariy. Darüber hinaus verwendet diese Lösung Inhalts-URIs anstelle von direkten Dateiverweisen.
RestClient
@Headers({
"Accept: application/json",
"Content-Type: application/octet-stream"
})
@POST("api/v1/upload")
Call<FileDTO> uploadFile(@Body RequestBody file);
ProgressRequestBody
public class ProgressRequestBody extends RequestBody {
private static final String LOG_TAG = ProgressRequestBody.class.getSimpleName();
public interface ProgressCallback {
public void onProgress(long progress, long total);
}
public static class UploadInfo {
public Uri contentUri;
public long contentLength;
}
private WeakReference<Context> mContextRef;
private UploadInfo mUploadInfo;
private ProgressCallback mListener;
private static final int UPLOAD_PROGRESS_BUFFER_SIZE = 8192;
public ProgressRequestBody(Context context, UploadInfo uploadInfo, ProgressCallback listener) {
mContextRef = new WeakReference<>(context);
mUploadInfo = uploadInfo;
mListener = listener;
}
@Override
public MediaType contentType() {
return MediaType.parse("application/octet-stream");
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
long fileLength = mUploadInfo.contentLength;
byte[] buffer = new byte[UPLOAD_PROGRESS_BUFFER_SIZE];
InputStream in = in();
long uploaded = 0;
try {
int read;
while ((read = in.read(buffer)) != -1) {
mListener.onProgress(uploaded, fileLength);
uploaded += read;
sink.write(buffer, 0, read);
}
} finally {
in.close();
}
}
@Override
public long contentLength() throws IOException {
return mUploadInfo.contentLength;
}
private InputStream in() throws IOException {
InputStream stream = null;
try {
stream = getContentResolver().openInputStream(mUploadInfo.contentUri);
} catch (Exception ex) {
Log.e(LOG_TAG, "Error getting input stream for upload", ex);
}
return stream;
}
private ContentResolver getContentResolver() {
if (mContextRef.get() != null) {
return mContextRef.get().getContentResolver();
}
return null;
}
}
So starten Sie den Upload:
ProgressRequestBody requestBody = new ProgressRequestBody(
getContext(),
new UploadInfo(myUri, fileSize),
new ProgressRequestBody.ProgressCallback() {
public void onProgress(long progress, long total) {
}
}
);
mRestClient.uploadFile(requestBody);
Warnung: Wenn Sie vergessen, die Funktion contentLength () zu überschreiben, werden möglicherweise einige undurchsichtige Fehler angezeigt:
retrofit2.adapter.rxjava.HttpException: HTTP 503 client read error
Oder
Write error: ssl=0xb7e83110: I/O error during system call, Broken pipe
Oder
javax.net.ssl.SSLException: Read error: ssl=0x9524b800: I/O error during system call, Connection reset by peer
Dies ist das Ergebnis eines mehrfachen Aufrufs von RequestBody.writeTo (), da die Standard-contentLength () -1 ist.
Wie auch immer, es hat lange gedauert, um herauszufinden, hoffe es hilft.
Nützliche Links:
https://github.com/square/retrofit/issues/1217