断点续传,听上去似乎是个比较高级的话题,本文只讲述一下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
![]()