Android開發 retrofit下載與上傳


前言

   此博客只講解retrofit下載與上傳的使用,其實與其說是retrofit的下載與上傳還不如說,依然是Okhttp的下載與上傳.如果你需要了解retrofit入門請查看這篇博客(此博客不在詳細講解一些基礎的東西):https://www.cnblogs.com/guanxinjing/p/11594249.html

下載

  設置下載接口

public interface HttpList {

    @Streaming //注解這個請求將獲取數據流,此后將不會這些獲取的請求數據保存到內存中,將交與你操作.
    @GET
    Call<ResponseBody> download(@Url String url);


}

這里有一個很重要的東西! @Url屬性, 這個屬性是你導入的下載地址. 它可以是絕對地址和可以是相對地址,當你使用這個屬性的時候,Retrofit設置基礎UrlbaseUrl("http://p.gdown.baidu.com/") 將自動判斷地址是絕對還是相對,從而選擇拼接Url還是替換Url !

  請求下載

private void downloadFile() {
        final File file = new File(getExternalCacheDir(), "demo.apk");
        if (file.exists()) {
            file.delete();
        }

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://p.gdown.baidu.com/")//base的網絡地址
                .callbackExecutor(Executors.newSingleThreadExecutor())//設置線程,如果不設置下載在讀取流的時候就會報錯
                .build();

        HttpList httpList = retrofit.create(HttpList.class);

        Call<ResponseBody> call = httpList.download(DOWNLOAD_URL_PATH);//下載地址  太長了所以我用DOWNLOAD_URL_PATH封裝了一下,不要誤解

        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                try {
                    long total = response.body().contentLength();//需要下載的總大小
                    long current = 0;
                    InputStream inputStream = response.body().byteStream();
                    FileOutputStream fileOutputStream = new FileOutputStream(file);
                    byte[] bytes = new byte[1024];
                    int len = 0;
                    while ((len = inputStream.read(bytes)) != -1) {
                        fileOutputStream.write(bytes, 0, len);
               fileOutputStream.flush(); current
= current + len; Log.e(TAG, "已經下載=" + current + " 需要下載=" + total); } fileOutputStream.flush(); fileOutputStream.close(); inputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { } }); }

以上的下載實現的關鍵點,其實是ResponseBody,而這個其實就是okhttp的請求接口后返回的響應body. Retrofit並沒有對這個進行封裝,所以如果你了解okhttp的使用,應該是輕輕松松的.

 

上傳

   上傳一般有好幾種情況:

  •   不需要進度的上傳
  •   需要進度的上傳
  •   批量上傳

無進度的文件上傳

  接口服務類

public interface HttpList {
    @Multipart
    @POST("test/upfile")
    Call<ResponseBody> upFile(@Part MultipartBody.Part part);
}

注意這里的Body是 MultipartBody

  上傳實現

/**
     * 無進度上傳
     */
    private void updateFile(){
        final File imageFile = new File(getExternalCacheDir() + "/image/demo.jpg");
        if (!imageFile.getParentFile().exists()){
            imageFile.getParentFile().mkdirs();
        }

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.doclever.cn:8090/mock/5ba0c147fa08107daa8c55c2/")
                .callbackExecutor(Executors.newSingleThreadExecutor())
                .build();
        HttpList list = retrofit.create(HttpList.class);

        //
        /*
         * "image/jpg" 是你要上傳的文件的格式 這個格式並不是固定的,是根據你的項目使用那些何種key也有很多是使用下面這個:
         *  RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), imageFile);
         */
        RequestBody requestFile = RequestBody.create(MediaType.parse("image/jpg"), imageFile);


        //注意這里的file是對應MultipartBody上傳文件的key名稱
        MultipartBody.Part multipartBody = MultipartBody.Part.createFormData("file", imageFile.getName(), requestFile);

        Call<ResponseBody> call = list.upFile(multipartBody);
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                try {
                    Log.e(TAG, "onResponse: 上傳成功 "+response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {

            }
        });


    }

有進度的文件上傳

/**
     * 有進度的上傳
     */
    private void updateFile(){
        final File imageFile = new File(getExternalCacheDir() + "/image/demo.jpg");
        if (!imageFile.getParentFile().exists()){
            imageFile.getParentFile().mkdirs();
        }

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.doclever.cn:8090/mock/5ba0c147fa08107daa8c55c2/")
                .callbackExecutor(Executors.newSingleThreadExecutor())
                .build();
        HttpList list = retrofit.create(HttpList.class);
RequestBody requestFile
= new RequestBody() { @Nullable @Override public MediaType contentType() { return MediaType.parse("image/jpg");//這里返回上傳的格式 根據項目情況也可以切換成"multipart/form-data" 等等其他格式 } @Override public void writeTo(BufferedSink sink) throws IOException { RandomAccessFile randomAccessFile = new RandomAccessFile(imageFile, "rw"); long totalLength = 0; long currentUpLength = 0; if (totalLength == 0) { totalLength = randomAccessFile.length(); } byte[] bytes = new byte[2048]; int len = 0; try { while ((len = randomAccessFile.read(bytes)) != -1) { sink.write(bytes, 0, len); currentUpLength = currentUpLength + len; Log.e(TAG, "writeTo: totalLength="+totalLength + " currentUpLength="+currentUpLength); } }catch (Exception e){ Log.e(TAG, "上傳中斷"); }finally { randomAccessFile.close();//關閉流 Log.e(TAG, "流關閉"); } } }; MultipartBody.Part multipartBody = MultipartBody.Part.createFormData("file", imageFile.getName(), requestFile); Call<ResponseBody> call = list.upFile(multipartBody); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { try { Log.e(TAG, "onResponse: 上傳成功 "+response.body().string()); } catch (IOException e) { e.printStackTrace(); } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { } }); }

批量上傳文件(無對應key的批量上傳)

   接口服務類

public interface HttpList {
    @Multipart
    @POST("test/upfileList")
    Call<ResponseBody> upFileList(@Part List<MultipartBody.Part> partList);
}

其他與單個上傳一致

批量上傳文件(有對應key的批量上傳)

   接口服務類

public interface HttpList {
    @Multipart
    @POST("test/upfileList")
    Call<ResponseBody> upFileList(@PartMap Map<String, RequestBody> map);
}

  實現批量上傳

private void updateFile3(){
        final File imageFile1 = new File(getExternalCacheDir() + "/image/demo_1.jpg");
        final File imageFile2 = new File(getExternalCacheDir() + "/image/demo_2.jpg");
        final File imageFile3 = new File(getExternalCacheDir() + "/image/demo_3.jpg");
        RequestBody requestFile1 = RequestBody.create(MediaType.parse("multipart/form-data"), imageFile1);
        RequestBody requestFile2 = RequestBody.create(MediaType.parse("multipart/form-data"), imageFile2);
        RequestBody requestFile3 = RequestBody.create(MediaType.parse("multipart/form-data"), imageFile3);
        Map<String, RequestBody> map = new HashMap<>();
        map.put("file1", requestFile1); //file1 就是需要上傳每個文件的key名稱
        map.put("file2", requestFile2);
        map.put("file3", requestFile3);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.doclever.cn:8090/mock/5ba0c147fa08107daa8c55c2/")
                .callbackExecutor(Executors.newSingleThreadExecutor())
                .build();
        HttpList list = retrofit.create(HttpList.class);
        Call<ResponseBody> call = list.upFileList(map);
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                //上傳成功

            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {

            }
        });

    }

 

 

 

 

 

 

 

 

 

 

 

end


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM