当前位置: 移动技术网 > IT编程>开发语言>Java > Java编程实现服务器端支持断点续传的方法(可支持快车、迅雷)

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

2019年07月22日  | 移动技术网IT编程  | 我要评论

本文实例讲述了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程序设计有所帮助。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网