欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java编程实现服务器端支持断点续传的方法(可支持快车、迅雷)

程序员文章站 2024-03-07 23:04:39
本文实例讲述了java编程实现服务器端支持断点续传的方法。分享给大家供大家参考,具体如下: 大家知道tomcat之流对静态资源可以实现断点续传支持,但是如果是一个被控制的...

本文实例讲述了java编程实现服务器端支持断点续传的方法。分享给大家供大家参考,具体如下:

大家知道tomcat之流对静态资源可以实现断点续传支持,但是如果是一个被控制的流,如有权限控制,或下载地址仅是个代理的时候,这时候需要自己实现断点续传的支持,小弟不才,这里提供基本断点续传[a-,-b,a-b]的简单实现,经验证,可支持迅雷7和火狐的多次断点续传。现贴出代码,大家共同分享:

servlet

import java.io.bufferedoutputstream;
import java.io.file;
import java.io.ioexception;
import java.io.randomaccessfile;
import java.io.unsupportedencodingexception;
import java.net.uri;
import java.net.urisyntaxexception;
import java.net.urldecoder;
import javax.servlet.servletexception;
import javax.servlet.servletoutputstream;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;
import com.bsteel.cloud.storage.servlet.base.baseservlet;
import com.bsteel.cloud.storage.utils.fileutil;
/**
 * 文件下载(支持断点续传【迅雷\快车\旋风\firefox\chrome】)
 * @author jdkleo
 *
 */
public class fileioservlet extends baseservlet {
 private static final long serialversionuid = 1l;
 @override
 protected void doget(httpservletrequest req, httpservletresponse resp)
   throws servletexception, ioexception {
  this.dopost(req, resp);
 }
 @override
 protected void dopost(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception{
  download(request,response);
 }
 /**
  * 文件下载
  * @param request
  * @param response
  * @throws unsupportedencodingexception 
  */
 private void download(httpservletrequest request,httpservletresponse response) throws unsupportedencodingexception {
  file downloadfile = getfile(request);
  long pos = fileutil.headersetting(downloadfile, request, response);
//  log.info("跳过"+pos);
  servletoutputstream os = null; 
  bufferedoutputstream out = null;
  randomaccessfile raf = null;
  byte b[] = new byte[1024];//暂存容器
  try {
   os = response.getoutputstream();
   out = new bufferedoutputstream(os);
   raf = new randomaccessfile(downloadfile, "r");
   raf.seek(pos);
   try {
    int n = 0;
    while ((n = raf.read(b, 0, 1024)) != -1) {
     out.write(b, 0, n);
    }
    out.flush();
   } catch(ioexception ie) {
   }
  } catch (exception e) {
   log.error(e.getmessage(), e);
  } finally {
   if (out != null) {
    try {
     out.close();
    } catch (ioexception e) {
     log.error(e.getmessage(), e);
    }
   }
   if (raf != null) {
    try {
     raf.close();
    } catch (ioexception e) {
     log.error(e.getmessage(), e);
    }
   }
  }
 }
 private file getfile(httpservletrequest request) throws unsupportedencodingexception {
  string uristr = request.getparameter("uri");
  if (null != uristr){
    uristr = urldecoder.decode(uristr,"utf-8");
    if (uristr.startswith("file://")){
     uristr = uristr.substring(7);
     return new file(uristr);
    }else if (uristr.startswith("hbase://")){
     try {
      return new file(new uri(uristr));
     } catch (urisyntaxexception e) {
      log.error(e.getmessage(),e);
     }
    }
  }
  throw new runtimeexception("it's not a real uri");
 }
}

range支持

import java.io.file;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;
/**
 * 文件处理工具
 * @author jdkleo
 *
 */
public class fileutil {
 /**
  * 断点续传支持
  * @param file
  * @param request
  * @param response
  * @return 跳过多少字节
  */
 public static long headersetting(file file,httpservletrequest request, httpservletresponse response) {
  long len = file.length();//文件长度
  if ( null == request.getheader("range") ){
   setresponse(new rangesettings(len),file.getname(),response);
   return 0;
  }
  string range = request.getheader("range").replaceall("bytes=", "");
  rangesettings settings = getsettings(len,range);
  setresponse(settings,file.getname(),response);
  return settings.getstart();
 }
 private static void setresponse(rangesettings settings,string filename, httpservletresponse response) {
  response.addheader("content-disposition", "attachment; filename=\"" + ioutil.toutf8string(filename) + "\"");
  response.setcontenttype( ioutil.setcontenttype(filename));// set the mime type.
  if (!settings.isrange())
  {
   response.addheader("content-length", string.valueof(settings.gettotallength()));
  }
  else
  {
   long start = settings.getstart();
   long end = settings.getend();
   long contentlength = settings.getcontentlength();
   response.setstatus(javax.servlet.http.httpservletresponse.sc_partial_content);
  response.addheader("content-length", string.valueof(contentlength));
  string contentrange = new stringbuffer("bytes ").append(start).append("-").append(end).append("/").append(settings.gettotallength()).tostring();
  response.setheader("content-range", contentrange);
  }
 }
 private static rangesettings getsettings(long len, string range) {
  long contentlength = 0;
  long start = 0;
  long end = 0;
  if (range.startswith("-"))// -500,最后500个
  {
    contentlength = long.parselong(range.substring(1));//要下载的量
    end = len-1;
    start = len - contentlength;
  }
  else if (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;
  }
  return new rangesettings(start,end,contentlength,len);
 }
}

range封装

public class rangesettings{
  private long start;
  private long end;
  private long contentlength;
  private long totallength;
  private boolean range;
  public rangesettings(){
   super();
  }
  public rangesettings(long start, long end, long contentlength,long totallength) {
   this.start = start;
   this.end = end;
   this.contentlength = contentlength;
   this.totallength = totallength;
   this.range = true;
  }
  public rangesettings(long totallength) {
   this.totallength = totallength;
  }
  public long getstart() {
   return start;
  }
  public void setstart(long start) {
   this.start = start;
  }
  public long getend() {
   return end;
  }
  public void setend(long end) {
   this.end = end;
  }
  public long getcontentlength() {
   return contentlength;
  }
  public void setcontentlength(long contentlength) {
   this.contentlength = contentlength;
  }
  public long gettotallength() {
   return totallength;
  }
  public void settotallength(long totallength) {
   this.totallength = totallength;
  }
  public boolean isrange() {
   return range;
  }
}

io流相关处理工具类

import java.io.inputstream;
public class ioutil {
 public static string setcontenttype(string returnfilename){
  string contenttype = "application/octet-stream";
  if (returnfilename.lastindexof(".") < 0)
   return contenttype;
  returnfilename = returnfilename.tolowercase();
  returnfilename = returnfilename.substring(returnfilename.lastindexof(".")+1);
  if (returnfilename.equals("html") || returnfilename.equals("htm") || returnfilename.equals("shtml")){
   contenttype = "text/html";
  } else if (returnfilename.equals("css")){
   contenttype = "text/css";
  } else if (returnfilename.equals("xml")){
   contenttype = "text/xml";
  } else if (returnfilename.equals("gif")){
   contenttype = "image/gif";
  } else if (returnfilename.equals("jpeg") || returnfilename.equals("jpg")){
   contenttype = "image/jpeg";
  } else if (returnfilename.equals("js")){
   contenttype = "application/x-javascript";
  } else if (returnfilename.equals("atom")){
   contenttype = "application/atom+xml";
  } else if (returnfilename.equals("rss")){
   contenttype = "application/rss+xml";
  } else if (returnfilename.equals("mml")){
   contenttype = "text/mathml"; 
  } else if (returnfilename.equals("txt")){
   contenttype = "text/plain";
  } else if (returnfilename.equals("jad")){
   contenttype = "text/vnd.sun.j2me.app-descriptor";
  } else if (returnfilename.equals("wml")){
   contenttype = "text/vnd.wap.wml";
  } else if (returnfilename.equals("htc")){
   contenttype = "text/x-component";
  } else if (returnfilename.equals("png")){
   contenttype = "image/png";
  } else if (returnfilename.equals("tif") || returnfilename.equals("tiff")){
   contenttype = "image/tiff";
  } else if (returnfilename.equals("wbmp")){
   contenttype = "image/vnd.wap.wbmp";
  } else if (returnfilename.equals("ico")){
   contenttype = "image/x-icon";
  } else if (returnfilename.equals("jng")){
   contenttype = "image/x-jng";
  } else if (returnfilename.equals("bmp")){
   contenttype = "image/x-ms-bmp";
  } else if (returnfilename.equals("svg")){
   contenttype = "image/svg+xml";
  } else if (returnfilename.equals("jar") || returnfilename.equals("var") || returnfilename.equals("ear")){
   contenttype = "application/java-archive";
  } else if (returnfilename.equals("doc")){
   contenttype = "application/msword";
  } else if (returnfilename.equals("pdf")){
   contenttype = "application/pdf";
  } else if (returnfilename.equals("rtf")){
   contenttype = "application/rtf";
  } else if (returnfilename.equals("xls")){
   contenttype = "application/vnd.ms-excel"; 
  } else if (returnfilename.equals("ppt")){
   contenttype = "application/vnd.ms-powerpoint";
  } else if (returnfilename.equals("7z")){
   contenttype = "application/x-7z-compressed";
  } else if (returnfilename.equals("rar")){
   contenttype = "application/x-rar-compressed";
  } else if (returnfilename.equals("swf")){
   contenttype = "application/x-shockwave-flash";
  } else if (returnfilename.equals("rpm")){
   contenttype = "application/x-redhat-package-manager";
  } else if (returnfilename.equals("der") || returnfilename.equals("pem") || returnfilename.equals("crt")){
   contenttype = "application/x-x509-ca-cert";
  } else if (returnfilename.equals("xhtml")){
   contenttype = "application/xhtml+xml";
  } else if (returnfilename.equals("zip")){
   contenttype = "application/zip";
  } else if (returnfilename.equals("mid") || returnfilename.equals("midi") || returnfilename.equals("kar")){
   contenttype = "audio/midi";
  } else if (returnfilename.equals("mp3")){
   contenttype = "audio/mpeg";
  } else if (returnfilename.equals("ogg")){
   contenttype = "audio/ogg";
  } else if (returnfilename.equals("m4a")){
   contenttype = "audio/x-m4a";
  } else if (returnfilename.equals("ra")){
   contenttype = "audio/x-realaudio";
  } else if (returnfilename.equals("3gpp") || returnfilename.equals("3gp")){
   contenttype = "video/3gpp";
  } else if (returnfilename.equals("mp4") ){
   contenttype = "video/mp4";
  } else if (returnfilename.equals("mpeg") || returnfilename.equals("mpg") ){
   contenttype = "video/mpeg";
  } else if (returnfilename.equals("mov")){
   contenttype = "video/quicktime";
  } else if (returnfilename.equals("flv")){
   contenttype = "video/x-flv";
  } else if (returnfilename.equals("m4v")){
   contenttype = "video/x-m4v";
  } else if (returnfilename.equals("mng")){
   contenttype = "video/x-mng";
  } else if (returnfilename.equals("asx") || returnfilename.equals("asf")){
   contenttype = "video/x-ms-asf";
  } else if (returnfilename.equals("wmv")){
   contenttype = "video/x-ms-wmv";
  } else if (returnfilename.equals("avi")){
   contenttype = "video/x-msvideo";
  }
  return contenttype;
 }
 // utf8转码
 public static string toutf8string(string s) {
  stringbuffer sb = new stringbuffer();
  int len = s.tochararray().length;
  for (int i = 0; i < len; i++) {
   char c = s.charat(i);
   if (c >= 0 && c <= 255) {
    sb.append(c);
   } else {
    byte[] b;
    try {
     b = character.tostring(c).getbytes("utf-8");
    } catch (exception ex) {
     system.out.println(ex);
     b = new byte[0];
    }
    for (int j = 0; j < b.length; j++) {
     int k = b[j];
     if (k < 0)
      k += 256;
     sb.append("%" + integer.tohexstring(k).touppercase());
    }
   }
  }
  string s_utf8 = sb.tostring();
  sb.delete(0, sb.length());
  sb.setlength(0);
  sb = null;
  return s_utf8;
 }
 public static inputstream skipfully(inputstream in,long howmany)throws exception{
 long remainning = howmany;
 long len = 0;
 while(remainning>0){
  len = in.skip(len);
  remainning -= len;
 }
 return in;
 }
}

注有些类比如ioutil方法来自于csdn的网友总结,另外此类还不支持多range配置如[a-b,c-d,-e]等。

希望本文所述对大家java程序设计有所帮助。