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程序设计有所帮助。