一个支持断点续传、多线程下载的servlet的实现(JavaWeb、JSP)

直接上源码


Servlet源码

protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
//获取文件URI
String path = URLDecoder.decode(request.getRequestURI().replace(
getServletContext().getContextPath() + "/download", ""),"UTF-8");
//获取文件
File file = (File) ManualBuffer.get(path);
if (file == null) {
DirectoryTree dt = DirectoryTree.getInstance();
file = dt.findByPath(path);
if (file == null) {
response.sendError(404);
return;
}
ManualBuffer.put(path, file);
}
//文件名
String filename=file.getFilename();
//获取文件读取对象
FileReader fr=file.getReader();
//获取浏览器类型
String browser=request.getHeader("user-agent");
// 设置响应头,206支持断点续传
int http_status=206;
if(browser.contains("MSIE"))
http_status=200;//200 响应头,不支持断点续传
response.reset();
response.setStatus(http_status);
//响应头
response.setContentType("application/octet-stream;charset=UTF-8");
try {
//下载起始位置
long since=0;
//下载结束位置
long until=file.getSize()-1;
//获取Range,下载范围
String range=request.getHeader("range");
if(range!=null){
//剖解range
range=range.split("=")[1];
String[] rs=range.split("-");
if(AuthFilter.isDigit(rs[0])){
since=Integer.parseInt(rs[0]);
}
if(rs.length>1&&AuthFilter.isDigit(rs[1])){
until=Integer.parseInt(rs[1]);
}
}
//设置响应头
response.setHeader("Accept-Ranges", "bytes");
response.setHeader("Content-Range", "bytes "+since+"-"+ until + "/"
+ file.getSize());
//文件名用ISO08859_1编码
response.setHeader("Content-Disposition", "attachment; filename=\"" +
new String(filename.getBytes(),"ISO8859_1")+ "\"");
response.setHeader("Content-Length", "" + (until-since+1));
System.out.println("download: "+filename);
//定位到请求位置
fr.seek(since);
byte[] buffer=new byte[128*1024];
int len;
boolean full=false;
//读取,输出流
while((len=fr.read(buffer))>0){
if(fr.tell()-1>until){
len=(int) (len-(fr.tell()-until-1));
full=true;
}
response.getOutputStream().write(buffer, 0, len);
if(full)
break;
}
//输出
response.getOutputStream().flush();
response.getOutputStream().close();
} catch (java.net.SocketException e) {
//连接断开
}finally{
if(fr!=null)
fr.close();
}
response.flushBuffer();
}


FileReader接口

public interface FileReader {

/**
* 移动文件指针到指定位置
* @param pos
* @throws IOException
*/
public void seek(long pos) throws IOException;

/**
* 获取文件指针位置
* @return 文件指针位置
* @throws IOException
*/
public long tell() throws IOException;

/**
* 从文件指针开始读取一段数据到数组中,返回读取的字节数
* @param byte数组
* @return 读取的字节数
* @throws IOException
*/
public int read(byte[] bytes) throws IOException;

/**
* 从文件指针开始读取一段数据到数组指定位置中,返回读取的字节数
* @param byte数组
* @param off数组偏移量
* @param len读取的最大字节数
* @return 读取的字节数
* @throws IOException
*/
public int read(byte[] bytes, int off, int len) throws IOException;

/**
* 关闭
*/
public void close();
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值