原理:主要是使用HTTP协议中range属性来取得资源的部分内容,由于一般服务是不对外直接听过url访问的,一般都是通过ID,在servlet中输出byte[]来实现,所以要想实现蹲点续传一般要自己实现服务端和客户端,客户端保持文件的下载和上传文件状态,可以保存在本地或者数据库中。宰金鑫中断时保持中断状态,在进行续传时,首先读出文件的状态,然后设置range属性信息发送续传请求。服务器收到续传请求,读取range属性值,从文件中读取数据,发送到客户端。上传和下载的原理是一样的。
客户端:
/**
* 实现断点续传的客户端
* @author uj
*
*/
public class LoadClient {
public static void load(int start, int end) throws Exception {
String endpoint = "http://localhost:8080/RestDemo/LoadServlet?id=5";;;
URL url = new URL(endpoint);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Content-Type", "text/plain;charset=UTF-8");
connection.setRequestProperty("RANGE","bytes="+start+"-"+end);//在header中增加range属性
connection.connect();
System.out.println(connection.getResponseCode());
System.out.println(connection.getContentLength());
System.out.println(connection.getContentType());
InputStream is = (InputStream) connection.getContent();
String filename = connection.getHeaderField("Content-Disposition");
filename = new String(filename.getBytes("ISO8859-1"),"UTF-8");
filename = filename.substring(filename.lastIndexOf("\\")+1);
System.out.println(filename);
RandomAccessFile raf = new RandomAccessFile("D:\\"+filename,"rw");
raf.seek(start);
byte[] buf = new byte[1024];
int len = 0;
while((len = is.read(buf))!=-1) {
raf.write(buf,0,len);
}
raf.close();
}
public static void main(String[] args) throws Exception {
// load(0,1000); //下载前1000个字节的数据
load(1001, 0); //下载剩余字节的数据
}
}
服务端:需要使用JavaEE开发工具和Tomcat服务器环境
/**
* 断点下载的服务端
*/
@WebServlet("/LoadServlet")
public class LoadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int id = Integer.parseInt(request.getParameter("id"));
System.out.println(request.getContextPath());
String path = request.getServletContext().getRealPath("load");
String filename = "";
if(id == 1){
filename = path+"1.jpg";
}else if(id == 2){
filename = path+"2.jpg";
}else if(id == 3){
filename = path+"3.jpg";
}else{
filename = path+"断点续传.txt";
}
RandomAccessFile raf = new RandomAccessFile(filename,"r");
String range = request.getHeader("RANGE");
int start = 0;
int end = 0;
if(null!=range && range.startsWith("bytes=")){
String[] values = range.split("=")[1].split("-");
start = Integer.parseInt(values[0]);
end = Integer.parseInt(values[1]);
}
int requestSize = 0;
if(end!=0 && end>start){
requestSize = end-start+1;
response.addHeader("content-length", ""+(requestSize));
}else{
requestSize=Integer.MAX_VALUE;
}
byte[] buf = new byte[1024];
response.setContentType("application/x-download");
filename = new String(filename.getBytes("UTF-8"),"ISO8859-1");
response.addHeader("Content-Disposition", "attachment;filename="+filename);
ServletOutputStream os = response.getOutputStream();
int needSize = requestSize;
raf.seek(start);
while(needSize > 0){
int len = raf.read(buf);
if(needSize<buf.length){
os.write(buf,0,needSize);
}else{
os.write(buf,0,len);
if(len<buf.length){
break;
}
}
needSize -=buf.length;
}
raf.close();
os.close();
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
其中文件:load断点续传.txt 文件要放在WebContent文件夹下
项目下载链接:http://download.youkuaiyun.com/download/studyofandroid/10249181