作者热门文章
- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Java编程实现服务器端支持断点续传的方法(可支持快车、迅雷)由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
本文实例讲述了Java编程实现服务器端支持断点续传的方法。分享给大家供大家参考,具体如下:
大家知道Tomcat之流对静态资源可以实现断点续传支持,但是如果是一个被控制的流,如有权限控制,或下载地址仅是个代理的时候,这时候需要自己实现断点续传的支持,小弟不才,这里提供基本断点续传[a-,-b,a-b]的简单实现,经验证,可支持迅雷7和火狐的多次断点续传。现贴出代码,大家共同分享:
Servlet 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
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支持 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
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封装 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
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流相关处理工具类 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
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程序设计有所帮助.
最后此篇关于Java编程实现服务器端支持断点续传的方法(可支持快车、迅雷)的文章就讲到这里了,如果你想了解更多关于Java编程实现服务器端支持断点续传的方法(可支持快车、迅雷)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我有以下正则表达式 /[a-zA-Z0-9_-]/ 当字符串只包含从 a 到z 大小写、数字、_ 和 -。 我的代码有什么问题? 能否请您向我提供一个简短的解释和有关如何修复它的代码示例? //var
我是一名优秀的程序员,十分优秀!