断点续传http head头信息分析及java实现

fmms 13年前
     <p>1,客户端第一次下载</p>    <p><br /> 客户端request head信息<br /> GET /test/micro.rar HTTP/1.1<br /> User-Agent: <br /> <span style="background-color:#ffff00;">RANGE: bytes=0-</span><br /> Host: 10.10.246.126:8983<br /> Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2<br /> Connection: keep-alive<br /> <br /> <br /> 服务端response head信息<br /> HTTP/1.1<span style="background-color:#ffff00;"> 206 Partial Content</span><br /> Last-Modified: Wed, 11 Jan 2012 03:09:24 GMT<br /> Content-Length: 392725947<br /> Accept-Ranges: bytes<br /> <span style="background-color:#ffff00;">Content-Range: bytes 0-392725946/392725947</span></p>    <p> </p>    <p>2,客户端断点续传</p>    <p> </p>    <p>客户端request head信息</p>    <p>GET /test/micro.rar HTTP/1.1<br /> User-Agent: <br /> <span style="background-color:#ffff00;">RANGE: bytes=147193856-</span><br /> Host: 10.10.246.126:8983<br /> Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2<br /> Connection: keep-alive<br /> <br /> 服务端response head信息</p>    <p>HTTP/1.1 206 Partial Content<br /> Last-Modified: Wed, 11 Jan 2012 03:09:24 GMT<br /> <span style="background-color:#ffff00;">Content-Length: 245532091</span><br /> Accept-Ranges: bytes<br /> <span style="background-color:#ffff00;">Content-Range: bytes 147193856-392725946/392725947</span></p>    <p> </p>    <p>3,客户端已经下载完毕后,再次下载</p>    <p>客户端request head信息</p> GET /test/micro.rar HTTP/1.1    <br /> User-Agent:     <br /> RANGE: bytes=392725947-    <br /> Host: 10.10.246.126:8983    <br /> Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2    <br /> Connection: keep-alive    <p> </p>    <p>服务端response head信息<br /> HTTP/1.1 <span style="background-color:#ffff00;">416 Requested Range Not Satisfiable</span><br /> Last-Modified: Wed, 11 Jan 2012 03:09:24 GMT<br /> Content-Length: 392725947<br /> Accept-Ranges: bytes<br /> <span style="background-color:#ffff00;">Content-Range: bytes */392725947</span></p>    <p> </p>    <p>根据以上特性,可以通过java构造支持断点续传功能服务器与客户端</p>    <p style="text-align:left;line-height:22px;border-right-width:0px;overflow-x:hidden;overflow-y:hidden;font-family:Verdana,Arial,Helvetica,sans-serif;border-top-width:0px;border-bottom-width:0px;color:#2e2e2e;font-size:14px;border-left-width:0px;"><strong>第一部分:服务器端代码:</strong></p>    <div style="border-bottom:#6c92ad 1px dashed;text-align:left;border-left:#6c92ad 1px dashed;padding-bottom:0px;line-height:19px;overflow-x:hidden;overflow-y:hidden;background-color:#edf1f6;list-style-type:none;margin:8px auto 0px;padding-left:0px;width:618px;padding-right:0px;font-family:'Lucida Console',Arial,Helvetica,sans-serif;height:auto;color:#333333;border-top:#6c92ad 1px dashed;border-right:#6c92ad 1px dashed;padding-top:0px;" class="codes">     File file = new File(location);      <br /> if (file.exists()) {      <br /> long p = 0;     <br /> long fileLength;     <br /> fileLength = file.length();     <br />     <br /> // get file content     <br /> InputStream ins = new FileInputStream(file);     <br /> bis = new BufferedInputStream(ins);      <br />     <br /> // tell the client to allow accept-ranges     <br /> response.reset();     <br /> response.setHeader("Accept-Ranges", "bytes");     <br />     <br /> // client requests a file block download start byte     <br /> if (request.getHeader("Range") != null) {      <br /> response.setStatus(javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT);     <br /> p = Long.parseLong(request.getHeader("Range")     <br /> .replaceAll("bytes=", "")     <br /> .replaceAll("-", "")     <br /> );      <br /> }     <br /> // support multi-threaded download     <br /> // respone format:     <br /> // Content-Length:[file size] - [client request start bytes from file block]     <br /> response.setHeader("Content-Length", new Long(fileLength - p).toString());     <br />     <br /> if (p != 0) {     <br /> // 断点开始     <br /> // 响应的格式是:     <br /> // Content-Range: bytes [文件块的开始字节]-[文件的总大小 - 1]/[文件的总大小]     <br /> String contentRange = new StringBuffer("bytes ")     <br /> .append(new Long(p).toString())     <br /> .append("-")     <br /> .append(new Long(fileLength - 1).toString())     <br /> .append("/")     <br /> .append(new Long(fileLength).toString())     <br /> .toString();     <br /> response.setHeader("Content-Range", contentRange);     <br /> // pointer move to seek     <br /> bis.skip(p);     <br /> }     <br />     <br /> String fileName = file.getName();     <br /> response.addHeader("Content-Disposition", "attachment;filename=" + fileName);     <br />     <br /> while ((size = bis.read(buf)) != -1) {     <br /> response.getOutputStream().write(buf,0,size);     <br /> response.getOutputStream().flush();      <br /> }     <br /> bis.close();    </div>    <p style="text-align:left;line-height:22px;border-right-width:0px;overflow-x:hidden;overflow-y:hidden;font-family:Verdana,Arial,Helvetica,sans-serif;border-top-width:0px;border-bottom-width:0px;color:#2e2e2e;font-size:14px;border-left-width:0px;"><strong>第二部分:客户端代码</strong></p>    <div style="border-bottom:#6c92ad 1px dashed;text-align:left;border-left:#6c92ad 1px dashed;padding-bottom:0px;line-height:19px;overflow-x:hidden;overflow-y:hidden;background-color:#edf1f6;list-style-type:none;margin:8px auto 0px;padding-left:0px;width:618px;padding-right:0px;font-family:'Lucida Console',Arial,Helvetica,sans-serif;height:auto;color:#333333;border-top:#6c92ad 1px dashed;border-right:#6c92ad 1px dashed;padding-top:0px;" class="codes">     <p style="border-right-width:0px;overflow-x:hidden;overflow-y:hidden;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;">public class TestDownload {</p>     <p style="border-right-width:0px;overflow-x:hidden;overflow-y:hidden;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;">/**<br /> * @param args<br /> */<br /> public static void main(String[] args) {<br /> // TODO Auto-generated method stub<br /> HttpURLConnection httpURLConnection = null;<br /> URL url = null;<br /> BufferedInputStream bis = null;<br /> byte[] buf = new byte[10240];<br /> int size = 0;<br /> String fileName = "aaa.zip";<br /> String filePath = "C:\\Users\\Desktop";<br /> String remoteUrl = "http://127.0.0.1:8080/down.zip";</p>     <p style="border-right-width:0px;overflow-x:hidden;overflow-y:hidden;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;">// 检查本地文件<br /> RandomAccessFile rndFile = null;<br /> File file = new File(filePath + "\\" + fileName);<br /> long remoteFileSize = getRemoteFileSzie(remoteUrl);<br /> long nPos = 0;<br /> <br /> if (file.exists()) { <br /> long localFileSzie = file.length();<br /> if (localFileSzie < remoteFileSize) { <br /> System.out.println("文件续传...");<br /> nPos = localFileSzie;<br /> } else {<br /> System.out.println("文件存在,重新下载...");<br /> file.delete();<br /> try {<br /> file.createNewFile();<br /> } catch (Exception e) {<br /> // TODO: handle exception<br /> e.printStackTrace();<br /> } <br /> }<br /> <br /> } else {<br /> // 建立文件<br /> try {<br /> file.createNewFile();<br /> } catch (Exception e) {<br /> // TODO: handle exception<br /> e.printStackTrace();<br /> } <br /> }<br /> <br /> // 下载文件<br /> try {<br /> url = new URL(remoteUrl); <br /> httpURLConnection = (HttpURLConnection)url.openConnection();<br /> // 设置User-Agent<br /> httpURLConnection.setRequestProperty("User-Agent", "Net");<br /> // 设置续传开始<br /> httpURLConnection.setRequestProperty("Range", "bytes=" + nPos + "-");<br /> // 获取输入流<br /> bis = new BufferedInputStream(httpURLConnection.getInputStream()); <br /> rndFile = new RandomAccessFile(filePath + "\\" + fileName, "rw");<br /> rndFile.seek(nPos);<br /> int i = 0;<br /> while ((size = bis.read(buf)) != -1) {<br /> //if (i > 500) break; <br /> rndFile.write(buf, 0, size);<br /> <br /> i++;<br /> }<br /> System.out.println("i=" + i);<br /> httpURLConnection.disconnect();<br /> } catch (Exception e) {<br /> // TODO: handle exception<br /> e.printStackTrace();<br /> }<br /> }</p>     <p style="border-right-width:0px;overflow-x:hidden;overflow-y:hidden;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;">public static long getRemoteFileSzie(String url) {<br /> long size = 0;<br /> try {<br /> HttpURLConnection httpUrl = (HttpURLConnection)(new URL(url)).openConnection();<br /> size = httpUrl.getContentLength();<br /> httpUrl.disconnect(); <br /> } catch (Exception e) {<br /> // TODO: handle exception<br /> e.printStackTrace();<br /> }<br /> return size;<br /> }<br /> }</p>    </div> 转自:    <a href="/misc/goto?guid=4959500609551179680" target="_blank">http://blog.csdn.net/tornadowp/article/details/7193433</a>