国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

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

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程序設計有所幫助。

延伸 · 閱讀

精彩推薦
884
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25
主站蜘蛛池模板: av在线入口| 亚洲久久 | 91精品国产欧美一区二区成人 | 中文字幕一区二区三区日韩精品 | 在线免费观看av的网站 | 欧美视频免费看 | 国产精品久久久久久久久久久久久久 | 成人在线小视频 | 精品国产乱码久久久久久丨区2区 | 精品国产一区二区三区久久久 | 一区二区三区日韩在线 | 久久精品国产一区二区三区不卡 | 欧美国产日韩一区 | 久久一区| 欧美在线一区二区 | 欧美一级免费高清 | 亚洲一区中文字幕 | 亚洲精品乱码久久久久久花季 | 精品无人乱码一区二区三区 | 国产精品久久久久精 | 黄色在线网站 | 精品午夜久久 | 伊人无码高清 | 久久久精品综合 | 媚黑视频| 亚洲成av人片在线观看香蕉 | 欧美天天 | 日韩中文字幕视频在线观看 | 免费看少妇高潮一级毛片特黄 | 久久99国产精一区二区三区 | 国产乱码一区二区三区在线观看 | 国内精品久久久久 | 6080yy午夜一二三区久久 | 色偷偷888欧美精品久久久 | 免费在线看a | 超碰一区二区三区 | 成人午夜免费视频 | 自拍视频在线观看 | 久久综合一区二区 | 久久亚洲综合 | 久久亚洲精品中文字幕 |