2025-02-10

基於HTTP的協議的網絡文件下載,工作原理建立在請求/響應模式(Request/Response)上:一個客戶端與服務器建立連接後,客戶端向Web服務器發出一個HTTP請求行;Web服務器在收到有效的請求後,返回一個狀態行或多個響應標題、一個空白行和相關文檔。HTTP協議使用的端口號,通常為80。開發基於http協議的網絡文件下載必須掌握HTTP協議,包括向服務器發送請求和獲取服務器響應狀態的過程。HTTP1.0協議不支持斷點續傳功能. 本文用java提供瞭一個簡單的實現.

1.HTTP協議工作方式
    基於HTTP協議的客戶/服務器模式的信息交換過程,它分四個過程:建立連接、發送請求信息、獲取服務器響應狀態、關閉連接。其中較為復雜的過程是:發送請求信息、獲取服務器響應狀態.
1)向服務器發送請求信息 
  一個HTTP請求由一個請求行、可選數目的請求標題、一個空白行,以及在POST情況下的一些額外的數據組成。請求行的格式是:
     Method Request-URI HTTP-Vsersion CRLF
      Method表示請求方法,如GET和POST
      Request-URI標識瞭要請求的資源,
      HTTP-Version表示請求的HTTP協議版本,
      CRLF表示回車換行。

     HTTP請求報文格式如下:
        HTTP Command:       //方法字段(GET方法,POST方法)
        URI:                //URL字段,發送請求至保存該網站的服務器。
        HTTP Version:       //http協議版本字段
        Accept:             //指示可被接受的請求回應的介質類型范圍列表。
        Accept-Language:    //限制瞭請求回應中首選的語言為簡體中文,否則使用默認值。
        Accept-Encoding:    //限制瞭回應中可接受的內容編碼值
        User-Agent:         //定義用戶代理,即發送請求的瀏覽器類型
        Host:               //定義瞭目標所在的主機
        Connection:         //告訴服務器使用連接類型

2)獲取服務器響應狀態 
  在發送HTTP請求行以後,程序就可以讀取服務器的響應狀態瞭。HTTP響應狀態行包括:HTTP 狀態碼和一些HTTP響應標題。 
  HTTP回應報文
        HTTP Version: HTTP/1.1       //服務器用的是HTTP/1.1版本
        HTTP Status: 200             //請求成功,信息可以讀取,包含在響應的報文中
        Date:                        //響應報文的時間
        Server:                      //響應報文的服務器
        X-Powered-By:                //表明運行環境
        Set- cookie:                 //
        Vary:                        // 
        Content-Length:             //表明實體的長度
        Connection:                 //告訴客戶機在報文發送完畢後連接的狀態
        Content-Type:              //表明實體中的對象類型(html文檔)
        Binary Data:              //二進制數據

狀態碼表示響應類型,常用的有:
1××  保留
2××  表示請求成功地接收
3××  為完成請求客戶需進一步細化請求
4××  客戶錯誤
5××  服務器錯誤
  在程序中間,如果讀到“HTTP/1.1 200 OK”這樣的字符串,表明欲下載文件存在、該服務器支持斷點續傳,可以使用多線程下載。如果讀到“HTTP/1.0 200 OK”這樣的字符串,表明欲下載文件存在、但該服務器不支持斷點續傳,隻可以使用單線程下載。

2.實現代碼

Java代碼 
import java.io.IOException;    
import java.io.InputStream;    
import java.io.RandomAccessFile;    
import java.net.HttpURLConnection;    
import java.net.URL;    
   
public class TestDownFile {    
 public static void main(String[] args){    
  String sURL ="http://localhost:8080/hrproject/book.rar";    
  int nStartPos=0;    
  int nRead=0;    
  String sName="book.rar";    
  String sPath="e:\\temp";    
  try {    
   URL url = new URL(sURL);    
  //打開連接    
   HttpURLConnection httpConnection = (HttpURLConnection) url    
     .openConnection();    
    //獲得文件長度    
   long nEndPos =getFileSize(sURL);    
   RandomAccessFile oSavedFile= new RandomAccessFile(sPath+"\\"+sName, "rw");    
   httpConnection.setRequestProperty("User-Agent", "Internet Explorer");    
   String sProperty = "bytes=" + nStartPos + "-";    
    //告訴服務器book.rar這個文件從nStartPos字節開始傳    
   httpConnection.setRequestProperty("RANGE", sProperty);    
   System.out.println(sProperty);    
   InputStream input = httpConnection.getInputStream();    
   byte[] b = new byte[1024];    
   //讀取網絡文件,寫入指定的文件中    
   while ((nRead = input.read(b, 0, 1024)) > 0   
     && nStartPos < nEndPos ) {    
    oSavedFile.write(b, 0, nRead);    
    nStartPos += nRead;    
   }    
   httpConnection.disconnect();    
  } catch (Exception e) {    
   e.printStackTrace();    
  }    
 }    
     
//  獲得文件長度    
 public static long getFileSize(String sURL) {    
  int nFileLength = -1;    
  try {    
   URL url = new URL(sURL);    
   HttpURLConnection httpConnection = (HttpURLConnection) url    
     .openConnection();    
   httpConnection.setRequestProperty("User-Agent", "Internet Explorer");    
   
   int responseCode = httpConnection.getResponseCode();    
   if (responseCode >= 400) {    
    System.err.println("Error Code : " + responseCode);    
    return -2; // -2 represent access is error    
   }    
   String sHeader;    
   for (int i = 1;; i++) {    
    sHeader = httpConnection.getHeaderFieldKey(i);    
    if (sHeader != null) {    
     if (sHeader.equals("Content-Length")) {    
      nFileLength = Integer.parseInt(httpConnection    
        .getHeaderField(sHeader));    
      break;    
     }    
    } else   
     break;    
   }    
  } catch (IOException e) {    
   e.printStackTrace();    
  } catch (Exception e) {    
   e.printStackTrace();    
  }    
  System.out.println(nFileLength);    
  return nFileLength;    
 }    
}   

作者“海納百川,有容乃大”
 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *