断点续传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>