优化后。我们解析请求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); } } }
L
loveme199
@loveme199