1. ホーム
  2. android

[解決済み] Retrofit 2で画像をアップロードする際、プログレスバーを表示させることは可能ですか?

2023-03-23 08:19:37

質問

現在、私は Retrofit 2 を使用していますが、私のサーバーに写真をアップロードしたいと思っています。 私は、古いバージョンでは TypedFile クラスでアップロードすることができます。そして、もしプログレスバーを使いたいのであれば、このクラスで writeTo メソッドを TypedFile クラスで使用されます。

を使用する場合、進捗状況を表示することは可能ですか? retrofit 2 ライブラリの使用時に進捗を表示することはできますか?

どのように解決するのですか?

まず、Retrofit 2のバージョンが2.0 beta2以上であることが必要です。 次に、新しいクラスを作成します。 RequestBody :

public class ProgressRequestBody extends RequestBody {
    private File mFile;
    private String mPath;
    private UploadCallbacks mListener;
    private String content_type;

  private static final int DEFAULT_BUFFER_SIZE = 2048;

    public interface UploadCallbacks {
        void onProgressUpdate(int percentage);
        void onError();
        void onFinish();
    }

コンテンツタイプを追加して、画像以外のタイプにも対応できるようにしました。

public ProgressRequestBody(final File file, String content_type,  final  UploadCallbacks listener) {
    this.content_type = content_type;
    mFile = file;
    mListener = listener;            
}



@Override
    public MediaType contentType() {
        return MediaType.parse(content_type+"/*");
    }

@Override
public long contentLength() throws IOException {
  return mFile.length();
}

@Override
public void writeTo(BufferedSink sink) throws IOException {
    long fileLength = mFile.length();
    byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
    FileInputStream in = new FileInputStream(mFile);
    long uploaded = 0;

try {
            int read;
            Handler handler = new Handler(Looper.getMainLooper());
            while ((read = in.read(buffer)) != -1) {

            // update progress on UI thread
                handler.post(new ProgressUpdater(uploaded, fileLength));

                uploaded += read;
                sink.write(buffer, 0, read);
            }
        } finally {
            in.close();
        }
}

private class ProgressUpdater implements Runnable {
        private long mUploaded;
        private long mTotal;
        public ProgressUpdater(long uploaded, long total) {
            mUploaded = uploaded;
            mTotal = total;
        }

        @Override
        public void run() {
            mListener.onProgressUpdate((int)(100 * mUploaded / mTotal));            
        }
    }
}

<ブロッククオート

3つ目は、インターフェイスの作成です。

@Multipart
    @POST("/upload")        
    Call<JsonObject> uploadImage(@Part MultipartBody.Part file);

<ブロッククオート

/* 上記のJsonObjectは独自のモデルで置き換えることができますので、この点だけ注意してください。 ということです。*/

これで、アップロードの進捗を確認することができます。 あなたの activity (または fragment ):

class MyActivity extends AppCompatActivity implements ProgressRequestBody.UploadCallbacks {

        ProgressBar progressBar;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            progressBar = findViewById(R.id.progressBar);

            ProgressRequestBody fileBody = new ProgressRequestBody(file, this);
            MultipartBody.Part filePart = 

            MultipartBody.Part.createFormData("image", file.getName(), fileBody);

            Call<JsonObject> request = RetrofitClient.uploadImage(filepart);

             request.enqueue(new Callback<JsonObject>() {
             @Override
             public void onResponse(Call<JsonObject> call,   Response<JsonObject> response) {
                if(response.isSuccessful()){
                /* Here we can equally assume the file has been downloaded successfully because for some reasons the onFinish method might not be called, I have tested it myself and it really not consistent, but the onProgressUpdate is efficient and we can use that to update our progress on the UIThread, and we can then set our progress to 100% right here because the file already downloaded finish. */
                  }
            }

            @Override
            public void onFailure(Call<JsonObject> call, Throwable t) {
                      /* we can also stop our progress update here, although I have not check if the onError is being called when the file could not be downloaded, so I will just use this as a backup plan just in case the onError did not get called. So I can stop the progress right here. */
            }
        });

      }

        @Override
        public void onProgressUpdate(int percentage) {
            // set current progress
            progressBar.setProgress(percentage);
        }

        @Override
        public void onError() {
            // do something on error
        }

        @Override
        public void onFinish() {
            // do something on upload finished,
            // for example, start next uploading at a queue
            progressBar.setProgress(100);
        }

}