斷點續傳,聽上去似乎是個比較高級的話題,本文只講述一下http版的斷點續傳,其他協議的大家可以自行研究。
http協議中,服務端實現斷點續傳首先需要讀取客戶端傳送的Range頭信息,比如“Range: bytes=12583394-”這個就是指原來正在下載的文件需要從第12583394字節繼續下載,然後我們利用java.io.File的skip方法,捨棄掉原文件的前n個字節,接着就繼續慢慢write吧。。。
但是客戶端又是如何判斷服務端是否支持斷點續傳的呢?主要就是Accept-Ranges和Content-Length頭信息。比如“Accept-Ranges:bytes”和“Content-Length:99999999”。有了這兩個頭信息,客戶端就認爲服務端是支持斷點續傳的了。
然後需要注意的是,假如客戶端剛纔由於某些原因,暫停了下載,現在恢復的時候,就會如前所述,傳來Range頭信息,這時候,我們的response就需要設置一下狀態碼,這裏應該設置成206(詳細解釋請看http://en.wikipedia.org/wiki/List_of_HTTP_status_codes),還有就是Content-Range頭信息,格式爲“bytes
x-(y-1)/y”,x就是客戶端傳來的開始字節位置,y就是文件長度。
理解了這些,再看看給出的實例代碼,實現起來就是十分簡單了。實例代碼:
04 |
import java.io.FileInputStream; |
05 |
import java.io.IOException; |
06 |
import java.io.OutputStream; |
08 |
import javax.servlet.ServletException; |
09 |
import javax.servlet.http.HttpServlet; |
10 |
import javax.servlet.http.HttpServletRequest; |
11 |
import javax.servlet.http.HttpServletResponse; |
13 |
public class
DownloadTestServlet extends
HttpServlet { |
15 |
protected
void doGet(HttpServletRequest req, HttpServletResponse resp) |
16 |
throws
ServletException, IOException { |
22 |
protected
void doPost(HttpServletRequest req, HttpServletResponse resp) |
23 |
throws
ServletException, IOException { |
26 |
String fileName = req.getParameter( "file" ); |
27 |
System.out.println( "The file is:"
+ fileName); |
28 |
OutputStream os =
null ; |
29 |
FileInputStream is =
null ; |
31 |
File f =
new File( "D:\\xx\\"
+ fileName); |
32 |
is =
new FileInputStream(f); |
33 |
long
fSize = f.length(); |
34 |
byte
xx[] = new
byte [ 4096 ]; |
35 |
resp.setHeader( "Accept-Ranges" ,
"bytes" ); |
36 |
resp.setHeader( "Content-Length" , fSize +
"" ); |
37 |
resp.setHeader( "Content-Disposition" ,
"attachment;filename=" |
39 |
if
(req.getHeader( "Range" ) !=
null ) { |
41 |
resp.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT); |
42 |
pos = Long.parseLong(req.getHeader( "Range" ) |
43 |
.replaceAll( "bytes=" ,
"" ).replaceAll( "-" ,
"" )); |
46 |
String contentRange =
new StringBuffer( "bytes " ) |
47 |
.append( new
Long(pos).toString()).append( "-" ) |
48 |
.append( new
Long(fSize - 1 ).toString()).append( "/" ) |
49 |
.append( new
Long(fSize).toString()).toString(); |
50 |
resp.setHeader( "Content-Range" , contentRange); |
51 |
System.out.println( "Content-Range="
+ contentRange); |
55 |
os = resp.getOutputStream(); |
65 |
}
catch (IOException e) { |
本實例代碼使用ff測試通過,但用360和the world等自帶的下載工具不能續傳,原因正在查找,歡迎討論~
*******************************************
@ 2010-11-30 21:29
不知道爲何就是不支持ie內核的瀏覽器自帶的下載工具進行斷點續傳。。。自行模擬ie內核瀏覽器客戶端,發完全一樣的http header到servlet,明顯能順利斷點續傳,初步估計是瀏覽器處理問題,最值得懷疑的是“Connection:close”,用ff,chrome,opera都沒有問題,都是keep-alive,求高手回答~!
轉自:http://www.shaojiahao.org/tag/%E6%96%AD%E7%82%B9%E7%BB%AD%E4%BC%A0