標籤:abs ati 資料 readline 儲存 資訊 位元組 ide else
public static class DownloadThread extends Thread{ private int threadId; private int startIndex; private int endIndex; private int lastPostion; public DownloadThread(int threadId,int startIndex,int endIndex){ this.threadId = threadId; this.startIndex = startIndex; this.endIndex = endIndex; } @Override public void run() { synchronized (DownloadThread.class) { runningTrheadCount = runningTrheadCount +1;//開啟一線程,線程數加1 } //分段請求網路連接,分段儲存檔案到本地 try{ URL url = new URL(path); HttpURLConnection openConnection = (HttpURLConnection) url.openConnection(); openConnection.setRequestMethod("GET"); openConnection.setConnectTimeout(5*1000); System.out.println("理論上下載: 線程:"+threadId+",開始位置:"+startIndex+";結束位置:"+endIndex); //讀取上次下載結束的位置,本次從這個位置開始直接下載。 File file2 = new File(threadId+".txt"); if(file2.exists()){ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file2))); String lastPostion_str = bufferedReader.readLine(); lastPostion = Integer.parseInt(lastPostion_str);//讀取檔案擷取上次下載的位置 //設定分段下載的頭資訊。 Range:做分段資料請求用的。 openConnection.setRequestProperty("Range", "bytes="+lastPostion+"-"+endIndex);//bytes:0-500:請求伺服器資源中0-500之間的位元組資訊 501-1000: System.out.println("實際下載1: 線程:"+threadId+",開始位置:"+lastPostion+";結束位置:"+endIndex); bufferedReader.close(); }else{ lastPostion = startIndex; //設定分段下載的頭資訊。 Range:做分段資料請求用的。 openConnection.setRequestProperty("Range", "bytes="+lastPostion+"-"+endIndex);//bytes:0-500:請求伺服器資源中0-500之間的位元組資訊 501-1000: System.out.println("實際下載2: 線程:"+threadId+",開始位置:"+lastPostion+";結束位置:"+endIndex); } System.out.println("getResponseCode"+openConnection.getResponseCode() ); if(openConnection.getResponseCode() == 206){//200:請求全部資源成功, 206代表部分資源請求成功 InputStream inputStream = openConnection.getInputStream(); //請求成功將流寫入本地檔案中,已經建立的佔位那個檔案中 RandomAccessFile randomAccessFile = new RandomAccessFile(filename, "rw"); randomAccessFile.seek(lastPostion);//設定隨機檔案從哪個位置開始寫。 //將流中的資料寫入檔案 byte[] buffer = new byte[1024]; int length = -1; int total = 0;//記錄本次線程下載的總大小 while((length= inputStream.read(buffer)) !=-1){ randomAccessFile.write(buffer, 0, length); total = total+ length; //去儲存當前線程下載的位置,儲存到檔案中 int currentThreadPostion = lastPostion + total;//計算出當前線程本次下載的位置 //建立隨機檔案儲存當前線程下載的位置 File file = new File(threadId+".txt"); RandomAccessFile accessfile = new RandomAccessFile(file, "rwd"); accessfile.write(String.valueOf(currentThreadPostion).getBytes()); accessfile.close(); } //關閉相關的流資訊 inputStream.close(); randomAccessFile.close(); System.out.println("線程:"+threadId+",下載完畢"); //當所有線程下載結束,刪除存放下載位置的檔案。 synchronized (DownloadThread.class) { runningTrheadCount = runningTrheadCount -1;//標誌著一個線程下載結束。 if(runningTrheadCount == 0 ){ System.out.println("所有線程下載完成"); for(int i =0 ;i< threadCount;i++){ File file = new File(i+".txt"); System.out.println(file.getAbsolutePath()); file.delete(); } } } } }catch (Exception e) { e.printStackTrace(); } super.run(); } }
上面代碼主要做了4 件事
1、設定分段下載的頭資訊;
2、分段下載網路資源
3、當中斷時把當前各個線程當前下載的位置分別儲存到一個臨時檔案中
4、下載完成後把臨時檔案刪除 上面代碼中都給出了詳細的注釋
其中有一點要注意
openConnection.setRequestProperty(“Range”, “bytes=”+lastPostion+”-“+endIndex);
如果”bytes=格式不對的話會導致設定不成功,返回的將不是部分資源的返回碼
另一個要說明的就是randomAccessFile.seek(startThread);是設定各個線程下載的開始位置
Java多線程斷點下載