Questa risposta è per Retrofit 1. Per la soluzione compatibile con Retrofit 2 see this answer.
Ho avuto lo stesso problema e finalmente riuscito a farlo. Prima stavo usando lib di primavera e quello che ho mostrato qui sotto ha funzionato per Spring ma era incoerente da quando ho fatto un errore nell'usarlo per InputStream. Ho spostato tutte le mie API per utilizzare il retrofit e il caricamento è stato l'ultimo della lista, ho appena scavalcato TypedFile writeTo() per aggiornarmi sui byte letti in OutputStream. Forse questo può essere migliorato ma come ho detto l'ho fatto quando stavo usando Spring, quindi l'ho riutilizzato. Questo è il codice per il caricamento e funziona per me sulla mia app, se si desidera il feedback del download, è possibile utilizzare @Streaming e leggere l'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]);
}
}
Il CountingTypedFile è solo una copia di TypedFile ma compreso il ProgressListener.
fonte
2014-07-16 04:08:31
Can voi elaborare il caso d'uso? Le richieste di retrofit più semplici sono così brevi da non richiedere gli indicatori di avanzamento, ma suppongo che tu stia utilizzando PUT o POST per caricare un file come un'immagine? – Hober
Precisely @Hober, suggeriresti di non utilizzare il retrofit per caricare un'immagine? E se sì, hai qualche consiglio? –
L'ho implementato qualche tempo fa ma non ho trovato la soluzione, quindi ho fatto una barra di progresso indeterminato. – NujnaH