Ta odpowiedź dotyczy Retrofit 1. Rozwiązanie kompatybilne z Retrofit 2 see this answer.
miałem ten sam problem i wreszcie udało się zrobić. Używałem wcześniej języka źródłowego, a to, co pokazałem poniżej, działało na wiosnę, ale było niespójne, odkąd popełniłem błąd, używając go dla InputStream. Przeniosłem wszystkie moje API, aby użyć retrofitu i upload był ostatnim na liście, właśnie przesłoniłem TypedFile writeTo(), aby zaktualizować mnie na bajtach odczytanych do OutputStream. Może to można poprawić, ale jak już powiedziałem, zrobiłem to, kiedy używałem Springa, więc po prostu ponownie go użyłem. To jest kod do przesłania i działa dla mnie w mojej aplikacji, jeśli chcesz pobrać opinię, możesz użyć @Streaming i przeczytać inputStream.
ProgressListener
public interface ProgressListener {
void transferred(long num);
}
CountingTypedFile
public class CountingTypedFile extends TypedFile {
private static final int BUFFER_SIZE = 4096;
private final ProgressListener listener;
public CountingTypedFile(String mimeType, File file, ProgressListener listener) {
super(mimeType, file);
this.listener = listener;
}
@Override public void writeTo(OutputStream out) throws IOException {
byte[] buffer = new byte[BUFFER_SIZE];
FileInputStream in = new FileInputStream(super.file());
long total = 0;
try {
int read;
while ((read = in.read(buffer)) != -1) {
total += read;
this.listener.transferred(total);
out.write(buffer, 0, read);
}
} finally {
in.close();
}
}
}
MyApiService
public interface MyApiService {
@Multipart
@POST("/files")
ApiResult uploadFile(@Part("file") TypedFile resource, @Query("path") String path);
}
SendFileTask
private class SendFileTask extends AsyncTask<String, Integer, ApiResult> {
private ProgressListener listener;
private String filePath;
private FileType fileType;
public SendFileTask(String filePath, FileType fileType) {
this.filePath = filePath;
this.fileType = fileType;
}
@Override
protected ApiResult doInBackground(String... params) {
File file = new File(filePath);
totalSize = file.length();
Logger.d("Upload FileSize[%d]", totalSize);
listener = new ProgressListener() {
@Override
public void transferred(long num) {
publishProgress((int) ((num/(float) totalSize) * 100));
}
};
String _fileType = FileType.VIDEO.equals(fileType) ? "video/mp4" : (FileType.IMAGE.equals(fileType) ? "image/jpeg" : "*/*");
return MyRestAdapter.getService().uploadFile(new CountingTypedFile(_fileType, file, listener), "/Mobile Uploads");
}
@Override
protected void onProgressUpdate(Integer... values) {
Logger.d(String.format("progress[%d]", values[0]));
//do something with values[0], its the percentage so you can easily do
//progressBar.setProgress(values[0]);
}
}
CountingTypedFile jest po prostu kopią TypedFile ale tym ProgressListener.
Czy ty opracować w przypadku użycia? Większość prostych wniosków o modernizację jest tak krótka, że nie wymagają wskaźników postępu, ale domyślam się, że używasz PUT lub POST do przesłania pliku podobnego do obrazu? – Hober
Precyzyjnie @Hober, czy zalecałbyś, aby nie używać modernizacji do przesyłania zdjęć? A jeśli tak, czy masz jakieś zalecenia? –
Zaimplementowałem to jakiś czas temu, ale nie mogłem znaleźć rozwiązania, więc zamiast tego zrobiłem nieokreślony pasek postępu. – NujnaH