Spring Boot文件下载使用Range header(部分下载)

4
我正在开发Spring Boot Rest服务,用于下载文件(完整文件或范围内的文件)。控制器中的请求将被传递到服务层,在那里我会对文件进行处理并返回它。
选项一: 我可以逐字节读取FileInputStream并直接将其写入输出流。但是在这个选项中,我需要将响应对象传递给服务层,而我不想这样做(因为服务层应该与Web组件解耦)。
选项二: 从服务层传递整个字节数组到控制器也可能不是一个好选择,因为我正在处理非常大的文件。
选项三: 如果要返回整个文件,则可以将FileInputStream传递给ResponseEntity,Spring可以负责流式处理,但我还需要处理根据范围标头从文件返回字节范围的情况。
如有任何意见或指示,请提出。如果需要更多信息,请告诉我。
1个回答

0
我建议您选择其他方案。这是我在项目中所做的:
  1. 从Range头中提取fromByte/toByte值,
  2. 将服务方法语义声明为以下内容:
    • byte[] getMediaFileContent(Long/UUID <fileId>, Long fromByte, Long toByte),
  3. 在服务方法中读取目标文件中指定的字节范围并返回字节数组,
  4. 在控制器中手动构建适当的ResponseEntity<>,同时指定所需的标头:
    • "Accept-Ranges": "bytes"
    • "Content-Type": <content-type> (例如 image/x video/y 或 application/octet-stream)
    • "Content-Length": <range length>
    • "Content-Range": String.format("bytes %s-%s/%s", fromByte, toByte, fileFullLength)
也许还有其他建议,但这没有什么复杂的,而且完美地运行了...
要将文件读入指定的字节范围,可以使用以下代码:
byte[] readByteRange(File file, long start, long end, boolean inclusive) throws IOException {
        try (FileInputStream inputStream = new FileInputStream(file)) {
            ByteArrayOutputStream bufferedOutputStream = new ByteArrayOutputStream();
            byte[] data = new byte[1024];
            int nRead;
            while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
                bufferedOutputStream.write(data, 0, nRead);
            }
            bufferedOutputStream.flush();
            if (inclusive) {
                ++end;
            }
            byte[] result = new byte[(int) (end - start)];
            System.arraycopy(bufferedOutputStream.toByteArray(), (int) start, result, 0, (int) (end - start));
            return result;
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接