2017-07-26 66 views
11

我下面的代碼下載文件工作正常,當不執行resume爲更好的閱讀更多的解決方案來實現並解決問題我知道我必須檢查Last-Modified標題並設置爲連接,通過互聯網實施下載文件的簡歷

,但我不能這樣做,因爲我得到錯誤,如android Cannot set request property after connection is made或我得到nullhttpURLConnection

我使用這個reference

getHeaderField heaser RET甕:

{ 
    null=[HTTP/1.1 200 OK], 
    Cache-Control=[public], 
    Connection=[keep-alive], 
    Content-Length=[8037404], 
    Content-Md5=[VEqXHCc/Off7a6D0gRFpiQ==], 
    Content-Type=[image/jpeg], 
    Date=[Tue, 19 Jan 2016 07:24:36 GMT], 
    Etag=["544a971c273f39f7fb6ba0f481116989"], 
    Expires=[Sat, 29 Jul 2017 10:07:00 GMT], 
    Last-Modified=[Thu, 18 Dec 2014 08:44:34 GMT], 
    Server=[bws], 
    X-Android-Received-Millis=[1501063623576], 
    X-Android-Response-Source=[NETWORK 200], 
    X-Android-Selected-Protocol=[http/1.1], 
    X-Android-Sent-Millis=[1501063623532] 
} 

現在我該如何設置,有恢復下載文件?

GitHub Link

public void run() { 
    final URL   url; 
    HttpURLConnection httpURLConnection = null; 
    try { 
     try { 
      url = new URL(mUrl); 
      String lastModified = httpURLConnection.getHeaderField("Last-Modified"); 
      if (!lastModified.isEmpty()) { 
       httpURLConnection.setRequestProperty("If-Range", lastModified); 
      } 
      httpURLConnection = (HttpURLConnection) url.openConnection(); 

      if (mFile.exists()) { 
       downloadedLength = mFile.length(); 
       Log.e("downloadedLength ", downloadedLength + ""); 
       httpURLConnection.setRequestProperty("Range", "bytes=" + downloadedLength + "-"); 
       fileOutputStream = new FileOutputStream(mFile, true); 
      } else { 
       fileOutputStream = new FileOutputStream(mFile); 
      } 
      httpURLConnection.setConnectTimeout(30000); 
      httpURLConnection.setReadTimeout(30000); 
      httpURLConnection.setRequestMethod("GET"); 
     } catch (IOException e) { 
     } 
     final int responseCode; 
     final int total; 
     try { 
      responseCode = httpURLConnection.getResponseCode(); 
      total = httpURLConnection.getContentLength(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      Log.e("ER UPDATE ", e.getMessage()); 
     } 
     if (responseCode == 200) { 
      try { 
       inputStream = httpURLConnection.getInputStream(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
       Log.e("IOException ", e.getMessage()); 
      } 
      final byte[] buffer = new byte[4 * 1024]; 
      int   length = -1; 
      int   finished = 0; 
      long   start = System.currentTimeMillis(); 
      try { 
       while ((length = inputStream.read(buffer)) != -1) { 
        if (!isDownloading()) { 
         throw new CanceledException("canceled"); 
        } 
        fileOutputStream.write(buffer, 0, length); 
        finished += length; 
        if (System.currentTimeMillis() - start > 1000) { 
         onDownloadProgressing(finished, total); 
         start = System.currentTimeMillis(); 
        } 
       } 
       onDownloadCompleted(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
       Log.e("ER UPDATE ", e.getMessage()); 
      } 
     } else { 
      Log.e("responseCode ", responseCode + ""); 
     } 
    } catch (DownloadException e) { 
     e.printStackTrace(); 
     Log.e("ER UPDATE ", e.getMessage()); 
    } catch (CanceledException e) { 
     e.printStackTrace(); 
     Log.e("ER UPDATE ", e.getMessage()); 
    } 
} 

而且我得到206響應代碼,而不是200

+1

爲什麼你不使用['DownloadManager'(https://developer.android.com/reference/android/app/DownloadManager.html),其中「在後臺下載,處理HTTP交互並在失敗後重試下載或跨連接更改和系統重新啓動「並已實現」恢復「? –

+0

@AndriiOmelchenko對於這個實現我找不到任何好的文檔 –

+0

DownloadManager正好用於下載文件,它的工作正常。試試[this](https://www.androidtutorialpoint.com/networking/android-download-manager-tutorial-download-file-using-download-manager-internet/)例子。 –

回答

4

1,因爲你正在嘗試初始化之前調用它,你是爲HttpURLConnection的越來越空,

即,此行

httpURLConnection = (HttpURLConnection) url.openConnection(); 

應該來這行之前:

String lastModified = httpURLConnection.getHeaderField("Last-Modified"); 

2-您可以在撥打connect()httpURLConnection 之前設置標題,因此您需要設置任何您想要的,然後connect()。這樣一來,你不應該得到錯誤(機器人無法設置連接後請求屬性)

3- 爲perfectly right,它就是你should expect使用Range時,這意味着部分內容成功和這就是你在做什麼,你得到的內容的一部分,如果你得到全部內容,你會得到。

所以要總結一下,你的代碼可以是這樣的: 注意:請按照// ***查看所需的更改。

編輯:這一切來到了此行

httpURLConnection.setRequestProperty("If-Range", lastModified); 

誤差得到,當你設置該屬性,

不管怎麼說,當你看看這個,這是毫無意義的拋出,你問最後修改的值等於剛剛從連接中獲得的值!, 如果要執行此操作,則需要在系統中存儲lastmodified,然後將其與URLConn中獲得的值進行比較,然後將c將它與您的文件長度(已經下載)012b進行比較,然後繼續完整下載或恢復下載。

找到新的代碼如下:

public void run() { 
    myLastModified = getLastModified(mFile.getName()); // get last stored value for this file (use file name or other key) 
    int total =0; 

    final URL   url; 
    HttpURLConnection httpURLConnection = null; 
    try { 
     try { 
      url = new URL(mUrl); 

      httpURLConnection = (HttpURLConnection) url.openConnection(); 
      httpURLConnection.setDoInput(true); 

      httpURLConnection.setConnectTimeout(30000); 
      httpURLConnection.setReadTimeout(30000); 
      httpURLConnection.setRequestMethod("GET"); 

      //*** new way to handle download process 
      total = httpURLConnection.getContentLength(); 
      if(mFile.exists()){ 
       if(mFile.length() == total){ 
        //we are done, return. 
        return; 
       }else{ 
        //file was not completly donwloaded, now check lastModified: 
        long lastModified = httpURLConnection.getLastModified();//this gets the header "Last-Modified" and convert to long 
        if (lastModified == myLastModified) { //myLastModified should be retrived on each download and stored locally on ur system 
         downloadedLength = mFile.length(); 
         Log.e("downloadedLength ", downloadedLength + ""); 
         httpURLConnection = (HttpURLConnection) url.openConnection(); 
         httpURLConnection.setDoInput(true); 

         httpURLConnection.setConnectTimeout(30000); 
         httpURLConnection.setReadTimeout(30000); 
         httpURLConnection.setRequestMethod("GET"); 

         httpURLConnection.setRequestProperty("Range", "bytes=" + downloadedLength + "-"+ total); //add + total (TO) 

         //append mode 
         fileOutputStream = new FileOutputStream(mFile, true); 
        }else{ 
         //file was modified after 1st uncompleted-download: 
         storeLastModified(lastModified, mFile.getName()); // use file name as key. can store in db or file ... 

         //don't set ant Range ... we want full download, with a fresh file 
         fileOutputStream = new FileOutputStream(mFile); 
        }//last mod IF 

       }//Length check 
      }else{ 
       //file not exist at all, create new file, set no Range we want full download... 
       mFile.createNewFile(); 
       fileOutputStream = new FileOutputStream(mFile); 
      }//file exists. 

     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     final int responseCode; 

     try { 
      responseCode = httpURLConnection.getResponseCode(); 

     } catch (IOException e) { 
      e.printStackTrace(); 
      Log.e("ER UPDATE ", e.getMessage()); 
     } 

     //***** 
     if (responseCode == 200 || responseCode == 206) { 
      try { 
       inputStream = httpURLConnection.getInputStream(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
       Log.e("IOException ", e.getMessage()); 
      } 
      final byte[] buffer = new byte[4 * 1024]; 
      int   length = -1; 
      int   finished = 0; 
      long   start = System.currentTimeMillis(); 
      try { 
       while ((length = inputStream.read(buffer)) != -1) { 
        if (!isDownloading()) { 
         throw new CanceledException("canceled"); 
        } 
        fileOutputStream.write(buffer, 0, length); 
        finished += length; 
        if (System.currentTimeMillis() - start > 1000) { 
         onDownloadProgressing(finished, total); 
         start = System.currentTimeMillis(); 
        } 
       } 
       onDownloadCompleted(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
       Log.e("ER UPDATE ", e.getMessage()); 
      } 
     } else { 
      Log.e("responseCode ", responseCode + ""); 
     } 
    } catch (DownloadException e) { 
     e.printStackTrace(); 
     Log.e("ER UPDATE ", e.getMessage()); 
    } catch (CanceledException e) { 
     e.printStackTrace(); 
     Log.e("ER UPDATE ", e.getMessage()); 
    } 
} 
+0

@ Mahdi.Pishguy,是的,你是對的,我沒有看着你的代碼(邏輯明智)現在我做了,我發現「if-range」沒有什麼意義,所以檢查我的新代碼,看看**編輯** – Yazan

+0

我得到這個錯誤'java.lang.IllegalStateException:已連接'這條線'httpURLConnection.setDoInput(true);'。我評論了'httpURLConnection.connect();',倉庫上git更新 –

+0

@ Mahdi.Pishguy刪除它,我給你發一條評論,刪除它,如果它導致問題。 – Yazan

1

看看this答案POMATu。 但無論如何,如果您通過HTTP協議下載文件,您可以使用DownloadManager - 系統服務(自API級別9開始)在後臺進行長時間運行的下載。它處理HTTP連接,連接更改,重啓,並確保每次下載都能成功完成。它已經支持恢復以及進度通知。

你可以找到許多教程,如this或例如that,以及stackoverflow標籤的許多解決方案。

+0

可能是你有權利,但它不是我的問題的答案 –

+0

這取決於你:)是的 - 這不是一個答案:只是通知你的問題的其他方法。可能會對某人有用。 –