java之断点续传简单实现

        断点续传主要是使用http协议中range的属性来取得资源的部分内容,由于一般服务是不对外直接提供url访问的,一般都是通过id,在servlet中输出byte[]来实现,所以要想实现断点续传一般要自己实现服务端和客户端,客户端保持文件的下载或上传状态,(保存在本地或者数据库中)。再进行中断时保持中断状态,在进行续传时,首先读出文件的状态,然后设置range属性信息发送续传请求。服务器收到续传请求,读取range属性值,从文件中读取数据,发送到客户端。上述是基本的原理,上传下载原理相同。

       下面模拟两次从服务器中现在文件。

       客户端:分多次取得部分文件内容,利用RandomAccessFile文件中读取数据,写到输出流中。

package org.nercita.zmx.servlet;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class LoadClient {
	
	public static void load(int start, int end) throws MalformedURLException, FileNotFoundException{
		
		String endpoint = "http://localhost:8080/RestDemo/servlet/LoadServlet?id=5";
			
		URL url = new URL(endpoint);
		try {
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setRequestProperty("Content-Type","text/plain; charset=UTF-8"); 
			conn.setRequestProperty("RANGE","bytes="+start+"-"+end); //header中增加range属性			
			conn.connect();
			System.out.println(conn.getResponseCode());
			System.out.println(conn.getContentLength());
			System.out.println(conn.getContentType());
			InputStream ins = (InputStream)conn.getContent();	
			String fileName=conn.getHeaderField("Content-Disposition");
			fileName = new String(fileName.getBytes("ISO8859-1"), "UTF-8");
			fileName=fileName.substring(fileName.lastIndexOf("\\")+1);
			System.out.println(fileName);
			RandomAccessFile raFile = new RandomAccessFile("E:\\"+fileName, "rw");
			raFile.seek(start);			
			byte[] buffer = new byte[4096];
			int len = -1;
			while((len = ins.read(buffer))!=-1){
				raFile.write(buffer,0,len);
			}
			raFile.close();
			conn.disconnect();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	
	public static void main(String[] args) throws IOException {
		
		load(0,1000);
		load(1001,0);

	
	}

}


 


服务端:获取分析range属性,从收入流读取内容字节流,利用RandomAccessFile输出到文件中。其中还解决了中文文件名乱码的问题,由于http协议中规定,当在网络中传输时,setHeader方法中的字符只能按ISO8859-1传输,所以这时候就要把Unicode字符转换成了ISO8859-1的编码传到客户端,客户端进行解码。否则会出现乱码。

package org.nercita.zmx.servlet;

import java.io.IOException;
import java.io.RandomAccessFile;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoadServlet extends HttpServlet {

	private static final long serialVersionUID = 237208504975097723L;

	public 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+"JDK_API_1_5_zh_CN.CHM";
		else if (id == 2)
			filename = path+"JDK_API_1_6_zh_CN.CHM";
		else if (id == 3)
			filename = path+"tomcat.gif";
		else
			filename = path+"\\断点续传text.txt";

		RandomAccessFile raFile = new RandomAccessFile(filename, "r");
		
		String range = request.getHeader("RANGE");
		int start=0, 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[] buffer = new byte[4096];			
		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;
		raFile.seek(start);
		while(needSize > 0){
			int len = raFile.read(buffer);
			if(needSize < buffer.length){
				os.write(buffer,0,needSize);
			} else {
				os.write(buffer,0,len);
				if(len < buffer.length){
					break;
				}
			}
			needSize -= buffer.length;
		}
			
		raFile.close();
		os.close();


	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
    
		 this.doGet(request, response);

	}

}


             上述代码,已通过本人测试,有兴趣的可以一试!

 


 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值