2017-09-14 146 views
0

我得到一个URL作为回应。我想下载该网址的html,以便用户也可以脱机看到它。它是一个recyclerView,其中每个项目都包含一个URL。所以当用户点击一个项目的URL时,它应该将其保存在外部磁盘中。使用Retrofit从URL下载HTML文件

下面是代码:

NewsAdapter:

case R.id.save: 
         Gson gson = new GsonBuilder() 
           .setLenient() 
           .create(); 
         Retrofit retrofit = new Retrofit.Builder() 
           .baseUrl("https://www.nytimes.com/") 
           .addConverterFactory(GsonConverterFactory.create(gson)) 
           .build(); 
         Log.i("Retrofit build", "initiated"); 
         ApiInterface retrofitInterface = retrofit.create(ApiInterface.class); 

           final Call<ResponseBody> call = retrofitInterface.downloadFileWithDynamicUrlSync("2017/09/13/us/nursing-home-deaths-florida.html"); 

         Log.i("Retrofit req execute", "initiated"); 

          new AsyncTask<Void, Void, Void>() { 
           @Override 
           protected Void doInBackground(Void... voids) { 
            boolean writtenToDisk = false; 
            try { 
             writtenToDisk = writeResponseBodyToDisk(call.execute().body()); 
            } catch (IOException e) { 
             e.printStackTrace(); 
            } 
            ; 

            Log.d("success", "file download was a success? " + writtenToDisk); 
            return null; 
           } 
          }.execute(); 


         break; 

private boolean writeResponseBodyToDisk(ResponseBody body) { 
     try { 
      // todo change the file location/name according to your needs 
      File futureStudioIconFile = new File(Environment.DIRECTORY_DOWNLOADS + File.separator + "Future Studio Icon.png"); 

      InputStream inputStream = null; 
      OutputStream outputStream = null; 

      try { 
       byte[] fileReader = new byte[4096]; 

       long fileSize = body.contentLength(); 
       long fileSizeDownloaded = 0; 

       inputStream = body.byteStream(); 
       outputStream = new FileOutputStream(futureStudioIconFile); 

       while (true) { 
        int read = inputStream.read(fileReader); 

        if (read == -1) { 
         break; 
        } 

        outputStream.write(fileReader, 0, read); 

        fileSizeDownloaded += read; 

        Log.d("filedownload", "file download: " + fileSizeDownloaded + " of " + fileSize); 
       } 

       outputStream.flush(); 

       return true; 
      } catch (IOException e) { 
       return false; 
      } finally { 
       if (inputStream != null) { 
        inputStream.close(); 
       } 

       if (outputStream != null) { 
        outputStream.close(); 
       } 
      } 
     } catch (IOException e) { 
      return false; 
     } 
    } 

ApiInterface:

// option 2: using a dynamic URL 
@Streaming 
    @GET 
    Call<ResponseBody> downloadFileWithDynamicUrlSync(@Url String fileUrl); 

我也遇到了错误:

Failed to invoke public com.squareup.okhttp.ResponseBody() with no args 

有人能告诉我如何至正确实施。

+0

“2017年/ 09/13 /美国/疗养院 - 死亡 - florida.html”。前缀domian名称下载文件。 –

回答

0

使用带域名的URL下载文件。删除流式注释并不需要。

您没有收到文件正文,因为您没有使用完整的网址。

像这样创建

@GET 
Call<ResponseBody> downloadFile(@Url String url); 

的接口然后使用此代码:

public void onResponse(Call<ResponseBody> call, Response<ResponseBody> 
response) 
         { 
          if (response.isSuccessful()) { 
           String filePath = Utils.downloadFile(response.body(),"filename"); 

          } 
         } 



public String downloadFile(ResponseBody body, String fileName) { 
    String filePath = null; 
    try { 
     int count; 
     byte data[] = new byte[1024 * 4]; 
     InputStream bis = new BufferedInputStream(body.byteStream(), 1024 * 8); 
     File storageDir = new File(Environment.getExternalStorageDirectory(), "AppName"); 
     if (!storageDir.exists()) { 
      storageDir.mkdirs(); 
     } 
     File outputFile = new File(storageDir, fileName); 
     OutputStream output = new FileOutputStream(outputFile); 
     while ((count = bis.read(data)) != -1) { 
      output.write(data, 0, count); 
     } 
     output.flush(); 
     output.close(); 
     bis.close(); 
     filePath = outputFile.getAbsolutePath(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return filePath; 
}