一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - Java基于Socket實現HTTP下載客戶端

Java基于Socket實現HTTP下載客戶端

2020-03-22 13:09gloomyfish JAVA教程

這篇文章主要介紹了Java基于Socket實現HTTP下載客戶端的相關資料,感興趣的小伙伴們可以參考一下

沒有借助任何第三方庫,完全基于JAVA Socket實現一個最小化的HTTP文件下載客戶端。完整的演示如何通過Socket實現下載文件的HTTP請求(request header)發送如何從Socket中接受HTTP響應(Response header, Response body)報文并解析與保存文件內容。如何通過SwingWork實現UI刷新,實時顯示下載進度。

首先看一下UI部分:

Java基于Socket實現HTTP下載客戶端

【添加下載】按鈕:

點擊彈出URL輸入框,用戶Copy要下載文件URL到輸入框以后,點擊[OK]按鈕即開始

下載

Java基于Socket實現HTTP下載客戶端

【清除完成】按鈕:

清除所有已經下載完成的文件列表

文件下載狀態分為以下幾種:

?
1
2
3
4
5
6
7
8
package com.gloomyfish.socket.tutorial.http.download;
 
public enum DownLoadStatus {
  NOT_STARTED,
  IN_PROCESS,
  COMPLETED,
  ERROR
}

UI部分主要是利用Swing組件完成。點擊【添加下載】執行的代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
final JDialog dialog = new JDialog(this,"Add File Link",true);
dialog.getContentPane().setLayout(new BorderLayout());
// dialog.setSize(new Dimension(400,200));
final URLFilePanel panel = new URLFilePanel();
panel.setUpListener(new ActionListener(){
  @Override
  public void actionPerformed(ActionEvent e) {
    if("OK".equals(e.getActionCommand())){
      if(panel.validateInput()) {
        DownloadDetailStatusInfoModel data = new DownloadDetailStatusInfoModel(panel.getValidFileURL());
        tableModel.getData().add(data);
        startDownlaod();
        refreshUI();
      }
      dialog.setVisible(false);
      dialog.dispose();
    } else if("Cancel".equals(e.getActionCommand())) {
      dialog.setVisible(false);
      dialog.dispose();
    }
  }});
 
dialog.getContentPane().add(panel, BorderLayout.CENTER);
dialog.pack();
centre(dialog);
dialog.setVisible(true);

【清除完成】按鈕執行的代碼如下:

?
1
2
3
4
5
6
7
8
9
10
private void clearDownloaded() {
  List<DownloadDetailStatusInfoModel> downloadedList = new ArrayList<DownloadDetailStatusInfoModel>();
  for(DownloadDetailStatusInfoModel fileStatus : tableModel.getData()) {
    if(fileStatus.getStatus().toString().equals(DownLoadStatus.COMPLETED.toString())) {
      downloadedList.add(fileStatus);
    }
  }
  tableModel.getData().removeAll(downloadedList);
  refreshUI();
}

讓JFrame組件居中顯示的代碼如下:

?
1
2
3
4
5
6
7
public static void centre(Window w) {
  Dimension us = w.getSize();
  Dimension them = Toolkit.getDefaultToolkit().getScreenSize();
  int newX = (them.width - us.width) / 2;
  int newY = (them.height - us.height) / 2;
  w.setLocation(newX, newY);
}

HTTP協議實現部分:

概述:HTTP請求頭與相應頭報文基本結構與解釋

HTTP請求:一個標準的HTTP請求報文如

Java基于Socket實現HTTP下載客戶端

其中請求頭可以有多個,message-body可以沒有,不是必須的。請求行的格式如下:

Request-Line = Method SP Request-URI SPHTTP-Version CRLF 舉例說明如下:

?
1
Request-Line = GET http://www.w3.org/pub/WWW/TheProject.htmlHTTP/1.1\r\n

其中SP表示空格, CRLF表示回車換行符\r\n

當你想要上傳文件時候,使用Post方式來填寫數據到message-body中即可。發送一個

簡單的HTTP請求報文如下:

  • GET /pub/WWW/TheProject.html HTTP/1.1\r\n
  • Host: www.w3.org\r\n
  • \r\n

HTTP響應:一個標準的HTTP響應報文如下

Java基于Socket實現HTTP下載客戶端

最先得到是狀態行,其格式如下:

Status-Line = HTTP-Version SP Status-CodeSP Reason-Phrase CRLF, 一個狀態行的簡單例子如下:Status-Line = HTTP/1.1 200 OK一般大家最喜歡的就是Status-Code會給你很多提示,最常見的就是404,500等狀態碼。狀態碼的意思可以參考RFC2616中的解釋。下載文件最要緊是的檢查HTTP響應頭中的Content-Length與Content-Type兩

個中分別聲明了文件的長度與文件的類型。其它如Accept-Ranges表示接受多少到多少的字節??赡茉诙嗑€程下載中使用。搞清楚了HTTP請求與響應的報文格式以后,我們就可以通過Socket按照報文格式解析內容,發送與讀取HTTP請求與響應。具體步驟

如下:

一、根據用戶輸入的文件URL建立Socket連接

?
1
2
3
4
5
6
7
8
9
10
11
URL url = new URL(fileInfo.getFileURL());
String host = url.getHost();
int port = (url.getPort() == -1) ? url.getDefaultPort():url.getPort();
System.out.println("Host Name = " + host);
System.out.println("port = " + port);
System.out.println("File URI = " + url.getFile());
 
// create socket and start to construct the request line
Socket socket = new Socket();
SocketAddress address = new InetSocketAddress(host, port);
socket.connect(address);

用了URL類來把用戶輸入的url string變成容易解析一點的URL。
二、構造HTTP請求

?
1
2
3
4
5
6
7
8
9
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF8"));
String requestStr = "GET " + url.getFile() + " HTTP/1.1\r\n"; // request line
 
// construct the request header - 構造HTTP請求頭(request header)
String hostHeader = "Host: " + host + "\r\n";
String acceptHeader = "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n";
String charsetHeader = "Accept-Charset: GBK,utf-8;q=0.7,*;q=0.3\r\n";
String languageHeader = "Accept-Language: zh-CN,zh;q=0.8\r\n";
String keepHeader = "Connection: close\r\n";

三、發送HTTP請求

?
1
2
3
4
5
6
7
8
9
// 發送HTTP請求
bufferedWriter.write(requestStr);
bufferedWriter.write(hostHeader);
bufferedWriter.write(acceptHeader);
bufferedWriter.write(charsetHeader);
bufferedWriter.write(languageHeader);
bufferedWriter.write(keepHeader);
bufferedWriter.write("\r\n"); // 請求頭信息發送結束標志
bufferedWriter.flush();

四、接受HTTP響應并解析內容,寫入創建好的文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 準備接受HTTP響應頭并解析
CustomDataInputStream input = new CustomDataInputStream(socket.getInputStream());
File myFile = new File(fileInfo.getStoreLocation() + File.separator + fileInfo.getFileName());
String content = null;
HttpResponseHeaderParser responseHeader = new HttpResponseHeaderParser();
BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(myFile));
boolean hasData = false;
while((content = input.readHttpResponseHeaderLine()) != null) {
  System.out.println("response header contect -->> " + content);
  responseHeader.addResponseHeaderLine(content);
  if(content.length() == 0) {
    hasData = true;
  }
  if(hasData) {
    int totalBytes = responseHeader.getFileLength();
    if(totalBytes == 0) break; // no response body and data
    int offset = 0;
    byte[] myData = null;
    if(totalBytes >= 2048) {
      myData = new byte[2048];
    } else {
      myData = new byte[totalBytes];
    }
    int numOfBytes = 0;
    while((numOfBytes = input.read(myData, 0, myData.length)) > 0 && offset < totalBytes) {
      offset += numOfBytes;
      float p = ((float)offset) / ((float)totalBytes) * 100.0f;
      if(offset > totalBytes) {
        numOfBytes = numOfBytes + totalBytes - offset;
        p = 100.0f;
      }
      output.write(myData, 0, numOfBytes);
      updateStatus(p);
    }
    hasData = false;
    break;
  }
}

簡單的HTTP響應頭解析類HttpResponseHeaderParser代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package com.gloomyfish.socket.tutorial.http.download;
 
import java.util.HashMap;
import java.util.Map;
 
/**
 * it can parse entity header, response head
 * and response line <status code, CharSet, ect...>
 * refer to RFC2616,關于HTTP響應頭,請看RFC文檔,描寫的很詳細?。?!
 */
public class HttpResponseHeaderParser {
  public final static String CONTENT_LENGTH = "Content-Length";
  public final static String CONTENT_TYPE = "Content-Type";
  public final static String ACCEPT_RANGES = "Accetp-Ranges";
   
  private Map<String, String> headerMap;
  public HttpResponseHeaderParser() {
    headerMap = new HashMap<String, String>();
  }
  /**
   * <p> get the response header key value pair </p>
   * @param responseHeaderLine
   */
  public void addResponseHeaderLine(String responseHeaderLine) {
    if(responseHeaderLine.contains(":")) {
      String[] keyValue = responseHeaderLine.split(": ");
      if(keyValue[0].equalsIgnoreCase(CONTENT_LENGTH)) {
        headerMap.put(CONTENT_LENGTH, keyValue[1]);
      } else if(keyValue[0].equalsIgnoreCase(CONTENT_TYPE)) {
        headerMap.put(CONTENT_TYPE, keyValue[1]);
      } else {
        headerMap.put(keyValue[0], keyValue[1]);
      }
    }
  }
   
  public int getFileLength() {
    if(headerMap.get(CONTENT_LENGTH) == null){
      return 0;
    }
    return Integer.parseInt(headerMap.get(CONTENT_LENGTH));
  }
   
  public String getFileType() {
    return headerMap.get(CONTENT_TYPE);
  }
  public Map<String, String> getAllHeaders() {
    return headerMap;
  }
 
}

以上就是本文的全部內容,希望對大家的學習java程序設計有所幫助。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日韩欧美一区二区不卡 | 国内精品视频免费观看 | 成 人 亚洲 综合天堂 | 国产suv精品 | 香蕉久久久 | 99r在线播放 | 亚洲国产精品久久久久久网站 | 久久精品无码一区二区日韩av | 国产成人综合久久 | 久久无码人妻AV精品一区 | 变态 调教 视频 国产九色 | 女班长的放荡日记高h | 97精品久久天干天天蜜 | 天堂网在线网站成人午夜网站 | 艹b视频在线观看 | 四虎永久网址在线观看 | 色777777女人色 | 久久精品99国产精品日本 | 色老板在线免费视频 | 国内自拍成人网在线视频 | 日本情趣视频 | 青青草伊人久久 | 国产精品一二区 | brazzersxxx欧美| 女人张开腿 让男人桶个爽 免费观看 | 无码国产成人777爽死在线观看 | 三级欧美在线 | 色悠久久久久综合欧美99 | 国产私拍精品88福利视频 | 91制片厂制作果冻传媒八夷 | 欧美在线一二三区 | 91香蕉导航| 91碰碰 | 色先锋 影音先锋a 资源站 | 好湿好紧太硬了我太爽了h 好湿好滑好硬好爽好深视频 | aika跟黑人太猛了 | 天天澡夜夜澡狠狠澡 | 国产一级一级一级成人毛片 | 性欧美video| 91精品久久一区二区三区 | 国产未成女年一区二区 |