0%

RandomAccessFile-分块加载

RandomAccessFile-分块加载

RandomAccessFile-分块加载

介绍

加载PDF时,按照自己设定的分块的大小,分多次请求。

RandomAccessFile可以从任意位置开始,任意位置结束读取文件内容。

效果

image-20200910154816957

前端

foxit-web-sdk

1
2
3
4
5
6
7
pdfui.openPDFByHttpRangeRequest({
range: {
//url: "http://127.0.0.1:8849/FoxitPDFSDKforWeb_DemoGuide.pdf",
url: "http://127.0.0.1:8849/foxit/"?pdfId=" + pdfId,
chunkSize: 131072
}
}

请求头Request Headers

1
2
3
4
Range: bytes=0-131071
Referer: http://127.0.0.1:8849/foxit/lib/WebPDFJRWorker.js?h=245349c6d66690b2cd6362d2643584e9
Sec-Fetch-Dest: empty
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.100 Safari/537.36

后端

controller

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
@GetMapping("/foxit")
public void foxit(HttpServletRequest request, HttpServletResponse response) {
int pdfId = Integer.parseInt(request.getParameter("pdfId"));

//获取文件
String filePath = foxitService.getPdfurl(pdfId);
if (filePath == null || "".equals(filePath)) {
return;
}

/* 不分片
response.setContentType("application/pdf");
// 读取路径下面的文件
try {
FileCopyUtils.copy(new FileInputStream(filePath),response.getOutputStream());
} catch (IOException e){
e.printStackTrace();
} */

File downloadFile = new File(filePath);
if (downloadFile == null){
return;
}

// 获取分片起始位置并处理
long downloadSize = downloadFile.length();
long fromPos = 0,toPos = 0;
String range = request.getHeader("Range");
String bytes = range.replaceAll("bytes=", "");
String[] ary = bytes.split("-");
fromPos = Long.parseLong(ary[0]);
if (ary.length == 2) {
toPos = Long.parseLong(ary[1]);
} else {
return;
}
if (toPos - fromPos > 131072)
return;
int size;
if (toPos > fromPos) {
size = (int) (toPos - fromPos + 1);
} else {
size = (int) (downloadSize - fromPos + 1);
}

/* 响应头 */
// 返回流信息 开始-结束/流总大小
response.setHeader("Content-Range", "bytes " + fromPos + "-" + toPos + "/" + downloadSize);
// 返回流大小
response.setHeader("Content-Length", size + "");
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", String.format("inline; filename=\"%s\"", downloadFile.getName()));
response.setHeader("Accept-Ranges", "bytes");
response.setHeader("Access-Control-Expose-Headers", "content-range, content-length, accept-ranges");// 坑点,前后端分离时必须添加
// 206
response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
response.setHeader("Connetion", "keep-alive");

// 返回流内容
downloadSize = size;
RandomAccessFile in = null;
OutputStream out = null;
try {
in = new RandomAccessFile(downloadFile, "r");
// 设置下载起始位置
if (fromPos > 0) {
in.seek(fromPos);
}
// 缓冲区大小
int bufLen = (int) (downloadSize < 2048 ? downloadSize : 2048);
byte[] buffer = new byte[bufLen];
int num;
int count = 0; // 当前写到客户端的大小
out = response.getOutputStream();
while ((num = in.read(buffer)) != -1) {
out.write(buffer, 0, num);
count += num;
//处理最后一段,计算不满缓冲区的大小
if (downloadSize - count < bufLen) {
bufLen = (int) (downloadSize - count);
if (bufLen == 0) {
break;
}
buffer = new byte[bufLen];
}
}
response.flushBuffer();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != out) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != in) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}
}

响应头Response Headers

1
2
3
4
5
6
7
8
9
10
11
Accept-Ranges: bytes
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET
Access-Control-Allow-Origin: http://127.0.0.1:8849
Access-Control-Expose-Headers: content-range, content-length, accept-ranges
Access-Control-Max-Age: 3600
Connetion: keep-alive
Content-Disposition: inline; filename="1.pdf"
Content-Length: 131072
Content-Range: bytes 0-131071/526889
Content-Type: application/pdf