Java编程实现服务器端支持断点续传的方法(可支持快车、迅雷)
本文实例讲述了Java编程实现服务器端支持断点续传的方法。分享给大家供大家参考,具体如下:
大家知道Tomcat之流对静态资源可以实现断点续传支持,但是如果是一个被控制的流,如有权限控制,或下载地址仅是个代理的时候,这时候需要自己实现断点续传的支持,小弟不才,这里提供基本断点续传[a-,-b,a-b]的简单实现,经验证,可支持迅雷7和火狐的多次断点续传。现贴出代码,大家共同分享:
Servlet
importjava.io.BufferedOutputStream;
importjava.io.File;
importjava.io.IOException;
importjava.io.RandomAccessFile;
importjava.io.UnsupportedEncodingException;
importjava.net.URI;
importjava.net.URISyntaxException;
importjava.net.URLDecoder;
importjavax.servlet.ServletException;
importjavax.servlet.ServletOutputStream;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importcom.bsteel.cloud.storage.servlet.base.BaseServlet;
importcom.bsteel.cloud.storage.utils.FileUtil;
/**
*文件下载(支持断点续传【迅雷\快车\旋风\Firefox\Chrome】)
*@authorjdkleo
*
*/
publicclassFileIoServletextendsBaseServlet{
privatestaticfinallongserialVersionUID=1L;
@Override
protectedvoiddoGet(HttpServletRequestreq,HttpServletResponseresp)
throwsServletException,IOException{
this.doPost(req,resp);
}
@Override
protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{
download(request,response);
}
/**
*文件下载
*@paramrequest
*@paramresponse
*@throwsUnsupportedEncodingException
*/
privatevoiddownload(HttpServletRequestrequest,HttpServletResponseresponse)throwsUnsupportedEncodingException{
FiledownloadFile=getFile(request);
longpos=FileUtil.headerSetting(downloadFile,request,response);
//log.info("跳过"+pos);
ServletOutputStreamos=null;
BufferedOutputStreamout=null;
RandomAccessFileraf=null;
byteb[]=newbyte[1024];//暂存容器
try{
os=response.getOutputStream();
out=newBufferedOutputStream(os);
raf=newRandomAccessFile(downloadFile,"r");
raf.seek(pos);
try{
intn=0;
while((n=raf.read(b,0,1024))!=-1){
out.write(b,0,n);
}
out.flush();
}catch(IOExceptionie){
}
}catch(Exceptione){
log.error(e.getMessage(),e);
}finally{
if(out!=null){
try{
out.close();
}catch(IOExceptione){
log.error(e.getMessage(),e);
}
}
if(raf!=null){
try{
raf.close();
}catch(IOExceptione){
log.error(e.getMessage(),e);
}
}
}
}
privateFilegetFile(HttpServletRequestrequest)throwsUnsupportedEncodingException{
StringuriStr=request.getParameter("uri");
if(null!=uriStr){
uriStr=URLDecoder.decode(uriStr,"UTF-8");
if(uriStr.startsWith("file://")){
uriStr=uriStr.substring(7);
returnnewFile(uriStr);
}elseif(uriStr.startsWith("hbase://")){
try{
returnnewFile(newURI(uriStr));
}catch(URISyntaxExceptione){
log.error(e.getMessage(),e);
}
}
}
thrownewRuntimeException("it'snotarealuri");
}
}
Range支持
importjava.io.File;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
/**
*文件处理工具
*@authorjdkleo
*
*/
publicclassFileUtil{
/**
*断点续传支持
*@paramfile
*@paramrequest
*@paramresponse
*@return跳过多少字节
*/
publicstaticlongheaderSetting(Filefile,HttpServletRequestrequest,HttpServletResponseresponse){
longlen=file.length();//文件长度
if(null==request.getHeader("Range")){
setResponse(newRangeSettings(len),file.getName(),response);
return0;
}
Stringrange=request.getHeader("Range").replaceAll("bytes=","");
RangeSettingssettings=getSettings(len,range);
setResponse(settings,file.getName(),response);
returnsettings.getStart();
}
privatestaticvoidsetResponse(RangeSettingssettings,StringfileName,HttpServletResponseresponse){
response.addHeader("Content-Disposition","attachment;filename=\""+IoUtil.toUtf8String(fileName)+"\"");
response.setContentType(IoUtil.setContentType(fileName));//settheMIMEtype.
if(!settings.isRange())
{
response.addHeader("Content-Length",String.valueOf(settings.getTotalLength()));
}
else
{
longstart=settings.getStart();
longend=settings.getEnd();
longcontentLength=settings.getContentLength();
response.setStatus(javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT);
response.addHeader("Content-Length",String.valueOf(contentLength));
StringcontentRange=newStringBuffer("bytes").append(start).append("-").append(end).append("/").append(settings.getTotalLength()).toString();
response.setHeader("Content-Range",contentRange);
}
}
privatestaticRangeSettingsgetSettings(longlen,Stringrange){
longcontentLength=0;
longstart=0;
longend=0;
if(range.startsWith("-"))//-500,最后500个
{
contentLength=Long.parseLong(range.substring(1));//要下载的量
end=len-1;
start=len-contentLength;
}
elseif(range.endsWith("-"))//从哪个开始
{
start=Long.parseLong(range.replace("-",""));
end=len-1;
contentLength=len-start;
}
else//从a到b
{
String[]se=range.split("-");
start=Long.parseLong(se[0]);
end=Long.parseLong(se[1]);
contentLength=end-start+1;
}
returnnewRangeSettings(start,end,contentLength,len);
}
}
Range封装
publicclassRangeSettings{
privatelongstart;
privatelongend;
privatelongcontentLength;
privatelongtotalLength;
privatebooleanrange;
publicRangeSettings(){
super();
}
publicRangeSettings(longstart,longend,longcontentLength,longtotalLength){
this.start=start;
this.end=end;
this.contentLength=contentLength;
this.totalLength=totalLength;
this.range=true;
}
publicRangeSettings(longtotalLength){
this.totalLength=totalLength;
}
publiclonggetStart(){
returnstart;
}
publicvoidsetStart(longstart){
this.start=start;
}
publiclonggetEnd(){
returnend;
}
publicvoidsetEnd(longend){
this.end=end;
}
publiclonggetContentLength(){
returncontentLength;
}
publicvoidsetContentLength(longcontentLength){
this.contentLength=contentLength;
}
publiclonggetTotalLength(){
returntotalLength;
}
publicvoidsetTotalLength(longtotalLength){
this.totalLength=totalLength;
}
publicbooleanisRange(){
returnrange;
}
}
IO流相关处理工具类
importjava.io.InputStream;
publicclassIoUtil{
publicstaticStringsetContentType(StringreturnFileName){
StringcontentType="application/octet-stream";
if(returnFileName.lastIndexOf(".")<0)
returncontentType;
returnFileName=returnFileName.toLowerCase();
returnFileName=returnFileName.substring(returnFileName.lastIndexOf(".")+1);
if(returnFileName.equals("html")||returnFileName.equals("htm")||returnFileName.equals("shtml")){
contentType="text/html";
}elseif(returnFileName.equals("css")){
contentType="text/css";
}elseif(returnFileName.equals("xml")){
contentType="text/xml";
}elseif(returnFileName.equals("gif")){
contentType="image/gif";
}elseif(returnFileName.equals("jpeg")||returnFileName.equals("jpg")){
contentType="image/jpeg";
}elseif(returnFileName.equals("js")){
contentType="application/x-javascript";
}elseif(returnFileName.equals("atom")){
contentType="application/atom+xml";
}elseif(returnFileName.equals("rss")){
contentType="application/rss+xml";
}elseif(returnFileName.equals("mml")){
contentType="text/mathml";
}elseif(returnFileName.equals("txt")){
contentType="text/plain";
}elseif(returnFileName.equals("jad")){
contentType="text/vnd.sun.j2me.app-descriptor";
}elseif(returnFileName.equals("wml")){
contentType="text/vnd.wap.wml";
}elseif(returnFileName.equals("htc")){
contentType="text/x-component";
}elseif(returnFileName.equals("png")){
contentType="image/png";
}elseif(returnFileName.equals("tif")||returnFileName.equals("tiff")){
contentType="image/tiff";
}elseif(returnFileName.equals("wbmp")){
contentType="image/vnd.wap.wbmp";
}elseif(returnFileName.equals("ico")){
contentType="image/x-icon";
}elseif(returnFileName.equals("jng")){
contentType="image/x-jng";
}elseif(returnFileName.equals("bmp")){
contentType="image/x-ms-bmp";
}elseif(returnFileName.equals("svg")){
contentType="image/svg+xml";
}elseif(returnFileName.equals("jar")||returnFileName.equals("var")||returnFileName.equals("ear")){
contentType="application/java-archive";
}elseif(returnFileName.equals("doc")){
contentType="application/msword";
}elseif(returnFileName.equals("pdf")){
contentType="application/pdf";
}elseif(returnFileName.equals("rtf")){
contentType="application/rtf";
}elseif(returnFileName.equals("xls")){
contentType="application/vnd.ms-excel";
}elseif(returnFileName.equals("ppt")){
contentType="application/vnd.ms-powerpoint";
}elseif(returnFileName.equals("7z")){
contentType="application/x-7z-compressed";
}elseif(returnFileName.equals("rar")){
contentType="application/x-rar-compressed";
}elseif(returnFileName.equals("swf")){
contentType="application/x-shockwave-flash";
}elseif(returnFileName.equals("rpm")){
contentType="application/x-redhat-package-manager";
}elseif(returnFileName.equals("der")||returnFileName.equals("pem")||returnFileName.equals("crt")){
contentType="application/x-x509-ca-cert";
}elseif(returnFileName.equals("xhtml")){
contentType="application/xhtml+xml";
}elseif(returnFileName.equals("zip")){
contentType="application/zip";
}elseif(returnFileName.equals("mid")||returnFileName.equals("midi")||returnFileName.equals("kar")){
contentType="audio/midi";
}elseif(returnFileName.equals("mp3")){
contentType="audio/mpeg";
}elseif(returnFileName.equals("ogg")){
contentType="audio/ogg";
}elseif(returnFileName.equals("m4a")){
contentType="audio/x-m4a";
}elseif(returnFileName.equals("ra")){
contentType="audio/x-realaudio";
}elseif(returnFileName.equals("3gpp")||returnFileName.equals("3gp")){
contentType="video/3gpp";
}elseif(returnFileName.equals("mp4")){
contentType="video/mp4";
}elseif(returnFileName.equals("mpeg")||returnFileName.equals("mpg")){
contentType="video/mpeg";
}elseif(returnFileName.equals("mov")){
contentType="video/quicktime";
}elseif(returnFileName.equals("flv")){
contentType="video/x-flv";
}elseif(returnFileName.equals("m4v")){
contentType="video/x-m4v";
}elseif(returnFileName.equals("mng")){
contentType="video/x-mng";
}elseif(returnFileName.equals("asx")||returnFileName.equals("asf")){
contentType="video/x-ms-asf";
}elseif(returnFileName.equals("wmv")){
contentType="video/x-ms-wmv";
}elseif(returnFileName.equals("avi")){
contentType="video/x-msvideo";
}
returncontentType;
}
//UTF8转码
publicstaticStringtoUtf8String(Strings){
StringBuffersb=newStringBuffer();
intlen=s.toCharArray().length;
for(inti=0;i<len;i++){
charc=s.charAt(i);
if(c>=0&&c<=255){
sb.append(c);
}else{
byte[]b;
try{
b=Character.toString(c).getBytes("utf-8");
}catch(Exceptionex){
System.out.println(ex);
b=newbyte[0];
}
for(intj=0;j<b.length;j++){
intk=b[j];
if(k<0)
k+=256;
sb.append("%"+Integer.toHexString(k).toUpperCase());
}
}
}
Strings_utf8=sb.toString();
sb.delete(0,sb.length());
sb.setLength(0);
sb=null;
returns_utf8;
}
publicstaticInputStreamskipFully(InputStreamin,longhowMany)throwsException{
longremainning=howMany;
longlen=0;
while(remainning>0){
len=in.skip(len);
remainning-=len;
}
returnin;
}
}
注有些类比如IoUtil方法来自于CSDN的网友总结,另外此类还不支持多Range配置如[a-b,c-d,-e]等。
希望本文所述对大家Java程序设计有所帮助。