------------------------------------前言
UVP会从我们服务器端取下载文件,有时会遇到比如:网络中断等异常情况导致文件下载中断
故:.net组同事提出了断点续传功能,我现在的理解就是接着上次下载的文件继续下载
“断点续传” ? 陌生的字眼、陌生的功能,没办法硬着头皮做吧!
------------------------------------正文
文件下载的入口处
public String downResourceFile() {
//文件路径
String path = StringUtil.getAppPath(this.getRequest(), savePath)+ "/" + adid + "/" + file;//注意:linux环境下不支持"\"
File fs=new File(path);
//下载文件配置(struts2默认封装的inputName不能支持断点续传)
this.getResponse().setContentType("application/zip");
this.getResponse().addHeader("Content-Disposition","attachment;fileName="+fs.getName());
byte[] bt = new byte[1024];
BufferedOutputStream os=new BufferedOutputStream(this.getResponse().getOutputStream());
if(this.getRequest().getHeader("Range") != null){
this.readFile(fs,bt,os);//断点续传
}else{//从开始进行下载
this.getResponse().setHeader("Content-Length",fs.length()+"");
inputStream=new FileInputStream(path);
int nRead;
//从输入流中读入字节流,然后写到文件中
while((nRead=inputStream.read(bt,0,1024))!=-1){
os.write(bt,0,nRead);
}
inputStream.close();
os.flush();
os.close();
}
// return success;//根据servlet原理抛:java.lang.IllegalStateException
// 具体原因: http://blog.sina.com.cn/s/blog_6151984a0100owod.html
return null;
}
/**
* 断点续传的方法
* @param fs 待下载文件
* @param bt 下载字节数
* @param os 返回给客户端的输出流
*/
private void readFile(File fs,byte[] bt,BufferedOutputStream os){
try{
String rangeBytes =this.getRequest().getHeader("Range").replaceAll("bytes=", "");
Long contentLength=null;//文件续传的长度
long pastLength=0;//文件续传的起点
RandomAccessFile raf=new RandomAccessFile(fs,"r");
if(rangeBytes.indexOf("-")==rangeBytes.length()-1){//针对 bytes=27000- 的请求
rangeBytes = rangeBytes.substring(0, rangeBytes.indexOf('-'));
pastLength=Long.parseLong(rangeBytes.trim());
contentLength=fs.length()-Long.parseLong(rangeBytes.trim())+1;
//设置读取内容的长度
this.getResponse().setHeader("Content-Length",contentLength.toString());
raf.seek(pastLength);//设置开始读取文件的位置
int nRead;
//从输入流中读入字节流,然后写到文件中
while((nRead=raf.read(bt,0,1024))!=-1){
os.write(bt,0,nRead);
}
}else{//针对 bytes=27000-39000 的请求
String temp0 = rangeBytes.substring(0,rangeBytes.indexOf('-'));
String temp2 = rangeBytes.substring(rangeBytes.indexOf('-') + 1, rangeBytes.length());
pastLength=Long.parseLong(temp0.trim());
contentLength=Long.parseLong(temp2)-Long.parseLong(temp0)+1;
//设置读取内容的长度
this.getResponse().setHeader("Content-Length",contentLength.toString());
raf.seek(pastLength-1);//设置开始读取文件的位置
int n = 0;
long readLength = 0;//记录已读字节数
while (readLength <= contentLength - 1024) {//大部分字节在这里读取
n = raf.read(bt, 0, 1024);
readLength += 1024;
os.write(bt, 0, n);
}
if (readLength <= contentLength) {//余下的不足 1024 个字节在这里读取
n = raf.read(bt, 0, (int)(contentLength - readLength));
os.write(bt, 0, n);
}
}
os.flush();
os.close();
raf.close();
}catch(Exception e){
e.printStackTrace();
}
}
-------------------------------------总结
折腾了一天总算是解决了各种问题
至此要感谢老大提供的链接:http://www.oschina.net/code/list_releted_codes?id=624
还要感谢.net小勇同学提供的实例:http://blog.youkuaiyun.com/defonds/article/details/7074352
感谢自己找到servlet报错方法:http://blog.sina.com.cn/s/blog_6151984a0100owod.html
感谢老大一路的全程指导,感谢小勇同学的连调过程中的积极配合!
最后还要感谢以上3个链接的博主提供的博客,是他们的点滴积累,促成了我现在顺利的完成工作!
还是送给自己的小诗:
try try try, and never say die; things will come right to you , by and by !