Servlet

Java代码 复制代码 收藏代码
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");
}
}
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支持 Java代码 复制代码 收藏代码
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);
} }
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封装 Java代码 复制代码 收藏代码
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;
} }
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流相关处理工具类 Java代码 复制代码 收藏代码
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;
} }
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;
} }

  

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 ArcSyncHttpDownloadServlet 源代码:

[java] view plaincopyprint?
01.package com.defonds.cds.common;
02.
03.import java.io.BufferedOutputStream;
04.import java.io.File;
05.import java.io.IOException;
06.import java.io.OutputStream;
07.import java.io.RandomAccessFile;
08.
09.import javax.servlet.ServletException;
10.import javax.servlet.http.HttpServlet;
11.import javax.servlet.http.HttpServletRequest;
12.import javax.servlet.http.HttpServletResponse;
13.
14.import org.apache.commons.logging.Log;
15.import org.apache.commons.logging.LogFactory;
16.
17.import com.defonds.cds.common.util.CommonUtil;
18.
19.//HTTP 断点续传 demo(客户端测试工具:快车、迅雷)
20.public class ArcSyncHttpDownloadServlet extends HttpServlet {
21. private static final long serialVersionUID = 1L;
22. final static Log log = LogFactory.getLog(ArcSyncHttpDownloadServlet.class);
23.
24. @Override
25. protected void doGet(HttpServletRequest req, HttpServletResponse resp)
26. throws ServletException, IOException {
27. this.doPost(req, resp);
28. }
29.
30. @Override
31. protected void doPost(HttpServletRequest request, HttpServletResponse response) {
32. File downloadFile = new File("D:/defonds/book/pattern/SteveJobsZH.pdf");//要下载的文件
33. long fileLength = downloadFile.length();//记录文件大小
34. long pastLength = 0;//记录已下载文件大小
35. int rangeSwitch = 0;//0:从头开始的全文下载;1:从某字节开始的下载(bytes=27000-);2:从某字节开始到某字节结束的下载(bytes=27000-39000)
36. long toLength = 0;//记录客户端需要下载的字节段的最后一个字节偏移量(比如bytes=27000-39000,则这个值是为39000)
37. long contentLength = 0;//客户端请求的字节总量
38. String rangeBytes = "";//记录客户端传来的形如“bytes=27000-”或者“bytes=27000-39000”的内容
39. RandomAccessFile raf = null;//负责读取数据
40. OutputStream os = null;//写出数据
41. OutputStream out = null;//缓冲
42. byte b[] = new byte[1024];//暂存容器
43.
44. if (request.getHeader("Range") != null) {// 客户端请求的下载的文件块的开始字节
45. response.setStatus(javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT);
46. log.info("request.getHeader(\"Range\")=" + request.getHeader("Range"));
47. rangeBytes = request.getHeader("Range").replaceAll("bytes=", "");
48. if (rangeBytes.indexOf('-') == rangeBytes.length() - 1) {//bytes=969998336-
49. rangeSwitch = 1;
50. rangeBytes = rangeBytes.substring(0, rangeBytes.indexOf('-'));
51. pastLength = Long.parseLong(rangeBytes.trim());
52. contentLength = fileLength - pastLength + 1;//客户端请求的是 969998336 之后的字节
53. } else {//bytes=1275856879-1275877358
54. rangeSwitch = 2;
55. String temp0 = rangeBytes.substring(0,rangeBytes.indexOf('-'));
56. String temp2 = rangeBytes.substring(rangeBytes.indexOf('-') + 1, rangeBytes.length());
57. pastLength = Long.parseLong(temp0.trim());//bytes=1275856879-1275877358,从第 1275856879 个字节开始下载
58. toLength = Long.parseLong(temp2);//bytes=1275856879-1275877358,到第 1275877358 个字节结束
59. contentLength = toLength - pastLength + 1;//客户端请求的是 1275856879-1275877358 之间的字节
60. }
61. } else {//从开始进行下载
62. contentLength = fileLength;//客户端要求全文下载
63. }
64.
65. /**
66. * 如果设设置了Content-Length,则客户端会自动进行多线程下载。如果不希望支持多线程,则不要设置这个参数。
67. * 响应的格式是:
68. * Content-Length: [文件的总大小] - [客户端请求的下载的文件块的开始字节]
69. * ServletActionContext.getResponse().setHeader("Content-Length",
70. * new Long(file.length() - p).toString());
71. */
72. response.reset();//告诉客户端允许断点续传多线程连接下载,响应的格式是:Accept-Ranges: bytes
73. response.setHeader("Accept-Ranges", "bytes");//如果是第一次下,还没有断点续传,状态是默认的 200,无需显式设置;响应的格式是:HTTP/1.1 200 OK
74. if (pastLength != 0) {
75. //不是从最开始下载,
76. //响应的格式是:
77. //Content-Range: bytes [文件块的开始字节]-[文件的总大小 - 1]/[文件的总大小]
78. log.info("----------------------------不是从开始进行下载!服务器即将开始断点续传...");
79. switch (rangeSwitch) {
80. case 1 : {//针对 bytes=27000- 的请求
81. String contentRange = new StringBuffer("bytes ").append(new Long(pastLength).toString()).append("-").append(new Long(fileLength - 1).toString()).append("/").append(new Long(fileLength).toString()).toString();
82. response.setHeader("Content-Range", contentRange);
83. break;
84. }
85. case 2 : {//针对 bytes=27000-39000 的请求
86. String contentRange = rangeBytes + "/" + new Long(fileLength).toString();
87. response.setHeader("Content-Range", contentRange);
88. break;
89. }
90. default : {
91. break;
92. }
93. }
94. } else {
95. //是从开始下载
96. log.info("----------------------------是从开始进行下载!");
97. }
98.
99. try {
100. response.addHeader("Content-Disposition", "attachment; filename=\"" + downloadFile.getName() + "\"");
101. response.setContentType( CommonUtil.setContentType(downloadFile.getName()));// set the MIME type.
102. response.addHeader("Content-Length", String.valueOf(contentLength));
103. os = response.getOutputStream();
104. out = new BufferedOutputStream(os);
105. raf = new RandomAccessFile(downloadFile, "r");
106. try {
107. switch (rangeSwitch) {
108. case 0 : {//普通下载,或者从头开始的下载
109. //同1
110. }
111. case 1 : {//针对 bytes=27000- 的请求
112. raf.seek(pastLength);//形如 bytes=969998336- 的客户端请求,跳过 969998336 个字节
113. int n = 0;
114. while ((n = raf.read(b, 0, 1024)) != -1) {
115. out.write(b, 0, n);
116. }
117. break;
118. }
119. case 2 : {//针对 bytes=27000-39000 的请求
120. raf.seek(pastLength - 1);//形如 bytes=1275856879-1275877358 的客户端请求,找到第 1275856879 个字节
121. int n = 0;
122. long readLength = 0;//记录已读字节数
123. while (readLength <= contentLength - 1024) {//大部分字节在这里读取
124. n = raf.read(b, 0, 1024);
125. readLength += 1024;
126. out.write(b, 0, n);
127. }
128. if (readLength <= contentLength) {//余下的不足 1024 个字节在这里读取
129. n = raf.read(b, 0, (int)(contentLength - readLength));
130. out.write(b, 0, n);
131. }
132.//
133.// raf.seek(pastLength);//形如 bytes=1275856879-1275877358 的客户端请求,找到第 1275856879 个字节
134.// while (raf.getFilePointer() < toLength) {
135.// out.write(raf.read());
136.// }
137. break;
138. }
139. default : {
140. break;
141. }
142. }
143. out.flush();
144. } catch(IOException ie) {
145. /**
146. * 在写数据的时候,
147. * 对于 ClientAbortException 之类的异常,
148. * 是因为客户端取消了下载,而服务器端继续向浏览器写入数据时,
149. * 抛出这个异常,这个是正常的。
150. * 尤其是对于迅雷这种吸血的客户端软件,
151. * 明明已经有一个线程在读取 bytes=1275856879-1275877358,
152. * 如果短时间内没有读取完毕,迅雷会再启第二个、第三个。。。线程来读取相同的字节段,
153. * 直到有一个线程读取完毕,迅雷会 KILL 掉其他正在下载同一字节段的线程,
154. * 强行中止字节读出,造成服务器抛 ClientAbortException。
155. * 所以,我们忽略这种异常
156. */
157. //ignore
158. }
159. } catch (Exception e) {
160. log.error(e.getMessage(), e);
161. } finally {
162. if (out != null) {
163. try {
164. out.close();
165. } catch (IOException e) {
166. log.error(e.getMessage(), e);
167. }
168. }
169. if (raf != null) {
170. try {
171. raf.close();
172. } catch (IOException e) {
173. log.error(e.getMessage(), e);
174. }
175. }
176. }
177. }
178.} ArcSyncHttpDownloadServlet 的 web.xml 配置清单: [html] view plaincopyprint?
01. <!-- HTTP 断点续传 demo:127.0.0.1/cds/http -->
02.<servlet>
03. <servlet-name>httpServlet</servlet-name>
04. <servlet-class>com.defonds.cds.common.ArcSyncHttpDownloadServlet</servlet-class>
05.</servlet>
06.<servlet-mapping>
07. <servlet-name>httpServlet</servlet-name>
08. <url-pattern>/http</url-pattern>
09.</servlet-mapping> ArcSyncHttpDownloadServlet 调用到的工具类 com.defonds.cds.common.util.CommonUtil 源代码: [java] view plaincopyprint?
01.package com.defonds.cds.common.util;
02.
03.public class CommonUtil {
04.
05. public static String setContentType(String returnFileName){
06. String contentType = "application/octet-stream";
07. if (returnFileName.lastIndexOf(".") < 0)
08. return contentType;
09. returnFileName = returnFileName.toLowerCase();
10. returnFileName = returnFileName.substring(returnFileName.lastIndexOf(".")+1);
11.
12. if (returnFileName.equals("html") || returnFileName.equals("htm") || returnFileName.equals("shtml")){
13. contentType = "text/html";
14. } else if (returnFileName.equals("css")){
15. contentType = "text/css";
16. } else if (returnFileName.equals("xml")){
17. contentType = "text/xml";
18. } else if (returnFileName.equals("gif")){
19. contentType = "image/gif";
20. } else if (returnFileName.equals("jpeg") || returnFileName.equals("jpg")){
21. contentType = "image/jpeg";
22. } else if (returnFileName.equals("js")){
23. contentType = "application/x-javascript";
24. } else if (returnFileName.equals("atom")){
25. contentType = "application/atom+xml";
26. } else if (returnFileName.equals("rss")){
27. contentType = "application/rss+xml";
28. } else if (returnFileName.equals("mml")){
29. contentType = "text/mathml";
30. } else if (returnFileName.equals("txt")){
31. contentType = "text/plain";
32. } else if (returnFileName.equals("jad")){
33. contentType = "text/vnd.sun.j2me.app-descriptor";
34. } else if (returnFileName.equals("wml")){
35. contentType = "text/vnd.wap.wml";
36. } else if (returnFileName.equals("htc")){
37. contentType = "text/x-component";
38. } else if (returnFileName.equals("png")){
39. contentType = "image/png";
40. } else if (returnFileName.equals("tif") || returnFileName.equals("tiff")){
41. contentType = "image/tiff";
42. } else if (returnFileName.equals("wbmp")){
43. contentType = "image/vnd.wap.wbmp";
44. } else if (returnFileName.equals("ico")){
45. contentType = "image/x-icon";
46. } else if (returnFileName.equals("jng")){
47. contentType = "image/x-jng";
48. } else if (returnFileName.equals("bmp")){
49. contentType = "image/x-ms-bmp";
50. } else if (returnFileName.equals("svg")){
51. contentType = "image/svg+xml";
52. } else if (returnFileName.equals("jar") || returnFileName.equals("var") || returnFileName.equals("ear")){
53. contentType = "application/java-archive";
54. } else if (returnFileName.equals("doc")){
55. contentType = "application/msword";
56. } else if (returnFileName.equals("pdf")){
57. contentType = "application/pdf";
58. } else if (returnFileName.equals("rtf")){
59. contentType = "application/rtf";
60. } else if (returnFileName.equals("xls")){
61. contentType = "application/vnd.ms-excel";
62. } else if (returnFileName.equals("ppt")){
63. contentType = "application/vnd.ms-powerpoint";
64. } else if (returnFileName.equals("7z")){
65. contentType = "application/x-7z-compressed";
66. } else if (returnFileName.equals("rar")){
67. contentType = "application/x-rar-compressed";
68. } else if (returnFileName.equals("swf")){
69. contentType = "application/x-shockwave-flash";
70. } else if (returnFileName.equals("rpm")){
71. contentType = "application/x-redhat-package-manager";
72. } else if (returnFileName.equals("der") || returnFileName.equals("pem") || returnFileName.equals("crt")){
73. contentType = "application/x-x509-ca-cert";
74. } else if (returnFileName.equals("xhtml")){
75. contentType = "application/xhtml+xml";
76. } else if (returnFileName.equals("zip")){
77. contentType = "application/zip";
78. } else if (returnFileName.equals("mid") || returnFileName.equals("midi") || returnFileName.equals("kar")){
79. contentType = "audio/midi";
80. } else if (returnFileName.equals("mp3")){
81. contentType = "audio/mpeg";
82. } else if (returnFileName.equals("ogg")){
83. contentType = "audio/ogg";
84. } else if (returnFileName.equals("m4a")){
85. contentType = "audio/x-m4a";
86. } else if (returnFileName.equals("ra")){
87. contentType = "audio/x-realaudio";
88. } else if (returnFileName.equals("3gpp") || returnFileName.equals("3gp")){
89. contentType = "video/3gpp";
90. } else if (returnFileName.equals("mp4") ){
91. contentType = "video/mp4";
92. } else if (returnFileName.equals("mpeg") || returnFileName.equals("mpg") ){
93. contentType = "video/mpeg";
94. } else if (returnFileName.equals("mov")){
95. contentType = "video/quicktime";
96. } else if (returnFileName.equals("flv")){
97. contentType = "video/x-flv";
98. } else if (returnFileName.equals("m4v")){
99. contentType = "video/x-m4v";
100. } else if (returnFileName.equals("mng")){
101. contentType = "video/x-mng";
102. } else if (returnFileName.equals("asx") || returnFileName.equals("asf")){
103. contentType = "video/x-ms-asf";
104. } else if (returnFileName.equals("wmv")){
105. contentType = "video/x-ms-wmv";
106. } else if (returnFileName.equals("avi")){
107. contentType = "video/x-msvideo";
108. }
109.
110. return contentType;
111. }
112.
113.
114.}

最新文章

  1. [转载]&ldquo;浅拷贝&rdquo;与&ldquo;深拷贝&rdquo;
  2. 12个滑稽的C语言面试问答——《12个有趣的C语言问答》评析(5)
  3. UI组件(思维导图)
  4. 建立交叉编译环境(arm-linux-gcc)
  5. Table &#39;.\mysql\proc&#39; is marked as crashed and should be repaired 报错
  6. UVa 1637 (概率) Double Patience
  7. [Linked List]Reverse Linked List,Reverse Linked List II
  8. [置顶] 大量相关gis资源网盘打包下载
  9. lesson - 8 Linux文档的压缩和打包
  10. android:background=&quot;@color/white&quot; [create file color.xml at res/values/]
  11. 从一个git仓库拷贝到另一个git仓库
  12. LeetCode算法题(长期更新)
  13. Java高级特性 第3节 java中常用的实用类(2)
  14. 软件工程第二次作业(One who wants to wear the crown, Bears the crown.)
  15. 【Struts2】剖析Struts2中的反射技术 ValueStack(值栈)
  16. win10 禁用Defender
  17. CentOS 6.3安装配置supervisor进程管理工具
  18. Tab Key not working when using Xfce remote desktop
  19. mysql访问权限GRANT ALL PRIVILEGES ON,访问权限表
  20. c#:Json字符串转成xml对象

热门文章

  1. 利用Loader来动态载入不同的QML文件来改变UI
  2. COCOS学习笔记--重力感应Acceleration
  3. 小程序 - tabBar
  4. Python--学习过程
  5. python实现的一个简单的网页爬虫
  6. NOI 2014简要题解
  7. iOS提交应用至App Store流程及真机调试 一,证书、配置文件
  8. HashMap源代码学习笔记
  9. USB/IP项目总结
  10. 我为什么不喜欢 CoreData