斷點續傳http head頭信息分析及java實現

fmms 12年前發布 | 30K 次閱讀 Java Java開發

1,客戶端第一次下載


客戶端request head信息
GET /test/micro.rar HTTP/1.1
User-Agent: 
RANGE: bytes=0-
Host: 10.10.246.126:8983
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive


服務端response head信息
HTTP/1.1 206 Partial Content
Last-Modified: Wed, 11 Jan 2012 03:09:24 GMT
Content-Length: 392725947
Accept-Ranges: bytes
Content-Range: bytes 0-392725946/392725947

 

2,客戶端斷點續傳

 

客戶端request head信息

GET /test/micro.rar HTTP/1.1
User-Agent: 
RANGE: bytes=147193856-
Host: 10.10.246.126:8983
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive

服務端response head信息

HTTP/1.1 206 Partial Content
Last-Modified: Wed, 11 Jan 2012 03:09:24 GMT
Content-Length: 245532091
Accept-Ranges: bytes
Content-Range: bytes 147193856-392725946/392725947

 

3,客戶端已經下載完畢后,再次下載

客戶端request head信息

GET /test/micro.rar HTTP/1.1
User-Agent: 
RANGE: bytes=392725947-
Host: 10.10.246.126:8983
Accept: text/html, image/gif, image/jpeg, ; q=.2, /; q=.2
Connection: keep-alive

 

服務端response head信息
HTTP/1.1 416 Requested Range Not Satisfiable
Last-Modified: Wed, 11 Jan 2012 03:09:24 GMT
Content-Length: 392725947
Accept-Ranges: bytes
Content-Range: bytes
/392725947</span></p>

 

根據以上特性,可以通過java構造支持斷點續傳功能服務器與客戶端

第一部分:服務器端代碼:

File file = new File(location); 
if (file.exists()) { 
long p = 0;
long fileLength;
fileLength = file.length();

// get file content
InputStream ins = new FileInputStream(file);
bis = new BufferedInputStream(ins); 

// tell the client to allow accept-ranges
response.reset();
response.setHeader("Accept-Ranges", "bytes");

// client requests a file block download start byte
if (request.getHeader("Range") != null) { 
response.setStatus(javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT);
p = Long.parseLong(request.getHeader("Range")
.replaceAll("bytes=", "")
.replaceAll("-", "")
); 
}
// support multi-threaded download
// respone format:
// Content-Length:[file size] - [client request start bytes from file block]
response.setHeader("Content-Length", new Long(fileLength - p).toString());

if (p != 0) {
// 斷點開始
// 響應的格式是:
// Content-Range: bytes [文件塊的開始字節]-[文件的總大小 - 1]/[文件的總大小]
String contentRange = new StringBuffer("bytes ")
.append(new Long(p).toString())
.append("-")
.append(new Long(fileLength - 1).toString())
.append("/")
.append(new Long(fileLength).toString())
.toString();
response.setHeader("Content-Range", contentRange);
// pointer move to seek
bis.skip(p);
}

String fileName = file.getName();
response.addHeader("Content-Disposition", "attachment;filename=" + fileName);

while ((size = bis.read(buf)) != -1) {
response.getOutputStream().write(buf,0,size);
response.getOutputStream().flush(); 
}
bis.close();

第二部分:客戶端代碼

public class TestDownload {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
HttpURLConnection httpURLConnection = null;
URL url = null;
BufferedInputStream bis = null;
byte[] buf = new byte[10240];
int size = 0;
String fileName = "aaa.zip";
String filePath = "C:\\Users\\Desktop";
String remoteUrl = "http://127.0.0.1:8080/down.zip";

// 檢查本地文件
RandomAccessFile rndFile = null;
File file = new File(filePath + "\\" + fileName);
long remoteFileSize = getRemoteFileSzie(remoteUrl);
long nPos = 0;

if (file.exists()) { 
long localFileSzie = file.length();
if (localFileSzie < remoteFileSize) { 
System.out.println("文件續傳...");
nPos = localFileSzie;
} else {
System.out.println("文件存在,重新下載...");
file.delete();
try {
file.createNewFile();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();

}

} else {
// 建立文件
try {
file.createNewFile();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();

}

// 下載文件
try {
url = new URL(remoteUrl); 
httpURLConnection = (HttpURLConnection)url.openConnection();
// 設置User-Agent
httpURLConnection.setRequestProperty("User-Agent", "Net");
// 設置續傳開始
httpURLConnection.setRequestProperty("Range", "bytes=" + nPos + "-");
// 獲取輸入流
bis = new BufferedInputStream(httpURLConnection.getInputStream()); 
rndFile = new RandomAccessFile(filePath + "\\" + fileName, "rw");
rndFile.seek(nPos);
int i = 0;
while ((size = bis.read(buf)) != -1) {
//if (i > 500) break; 
rndFile.write(buf, 0, size);

i++;
}
System.out.println("i=" + i);
httpURLConnection.disconnect();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}

public static long getRemoteFileSzie(String url) {
long size = 0;
try {
HttpURLConnection httpUrl = (HttpURLConnection)(new URL(url)).openConnection();
size = httpUrl.getContentLength();
httpUrl.disconnect(); 
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
return size;
}
}

轉自: http://blog.csdn.net/tornadowp/article/details/7193433

 本文由用戶 fmms 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!