优化后。我们解析请求header 中 Range实现分片下载。这样就能实现拖拽播放,不用将文件一次性全部下载完毕。
@GetMapping("/download")
public void download(HttpServletResponse res, HttpServletRequest request, @RequestParam("fileName") String fileName) {
GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(BUCKETNAME)
.object(fileName).build();
StatObjectArgs statObjectArgs = StatObjectArgs.builder().bucket(BUCKETNAME).object(fileName).build();
long fileSize;
try {
fileSize = minioClient.statObject(statObjectArgs).size();
} catch (Exception e) {
log.error("文件下载失败:{}", fileName, e);
return;
}
String range = request.getHeader("Range");
if(range != null && range.startsWith("bytes=")) {
try {
int idx = range.indexOf("-");
long start = Long.parseLong(range.substring("bytes=".length(), idx));
long end = minioClient.statObject(statObjectArgs).size() - 1;
if (idx + 1 < range.length()) {
end = Long.parseLong(range.substring(idx + 1));
}
long length = end - start + 1;
InputStream inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(BUCKETNAME).object(fileName).offset(start).length(length).build());
res.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
res.setHeader("Content-Range", "bytes " + start + "-" + end + "/" + fileSize);
res.setContentType("application/octet-stream");
res.setHeader("Content-Disposition", "attachment; filename=" + FileUtil.getName(fileName));
res.setContentLength((int)length);
try {
IOUtils.copy(inputStream, res.getOutputStream());
inputStream.close();
res.flushBuffer();
} catch (ClientAbortException e) {
// pass
}
} catch (Exception e) {
log.error("断点下载失败:{}", fileName, e);
}
} else {
try (InputStream is = minioClient.getObject(objectArgs)) {
res.setContentType("application/octet-stream");
res.addHeader("Content-Disposition", "attachment;filename=" + FileUtil.getName(fileName));
res.setContentLength((int)fileSize);
IOUtils.copy(is, res.getOutputStream());
res.flushBuffer();
} catch (Exception e) {
log.error("文件下载失败:{}", fileName, e);
}
}
}