You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot如何像PHP的readfile函数那样实时返回字节流?

实现Spring Boot流式转发网络文件接口

Java中可以通过流式传输实现类似PHP readfile的实时返回效果,核心是不将文件全部加载到内存,而是边读取远程文件流,边写入响应流返回给客户端。以下是针对你需求的优化实现:

修改后的完整代码

@Controller
@Api(tags = "文件转发")
@RequestMapping("/test")
@CrossOrigin
public class TestController {

    private final OkHttpClient okHttpClient = new OkHttpClient();

    @GetMapping("/get")
    @ApiOperation(value = "流式转发网络文件")
    public ResponseEntity<StreamingResponseBody> forwardFile(@RequestParam String fileUrl) throws IOException {
        // 构建远程文件请求
        Request request = new Request.Builder()
                .url(fileUrl)
                .get()
                .build();

        Response response = okHttpClient.newCall(request).execute();
        if (!response.isSuccessful()) {
            throw new IOException("远程文件请求失败: " + response);
        }

        // 获取远程文件的响应体流
        ResponseBody responseBody = response.body();
        if (responseBody == null) {
            throw new IOException("远程文件内容为空");
        }

        // 流式响应体,边读边写
        StreamingResponseBody streamingResponseBody = outputStream -> {
            try (InputStream inputStream = responseBody.byteStream()) {
                byte[] buffer = new byte[8192];
                int bytesRead;
                // 循环读取远程流,写入响应流
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                    // 强制刷新,确保数据实时发送给客户端
                    outputStream.flush();
                }
            } finally {
                response.close();
            }
        };

        // 设置响应头,让客户端正确识别文件
        return ResponseEntity.ok()
                .contentType(MediaType.parseMediaType(responseBody.contentType().toString()))
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + getFileName(fileUrl) + "\"")
                .body(streamingResponseBody);
    }

    // 从URL中提取文件名(简单实现,可根据需求优化)
    private String getFileName(String fileUrl) {
        int lastSlashIndex = fileUrl.lastIndexOf('/');
        return lastSlashIndex != -1 ? fileUrl.substring(lastSlashIndex + 1) : "download.file";
    }
}

关键说明

  • 使用GET请求:传递网络文件URL参数更符合REST规范,也更便于客户端调用。
  • 流式响应核心:StreamingResponseBody是Spring提供的专门用于流式传输的响应体,它会在服务器端逐步写入数据,同时客户端可以实时接收,不会占用大量内存。
  • 缓冲区读取:使用8KB的缓冲区循环读写,平衡性能和内存占用。
  • 资源自动关闭:通过try-with-resources确保输入流自动关闭,同时在finally中关闭OkHttp的Response,避免资源泄漏。
  • 响应头设置:传递远程文件的Content-Type,让客户端识别文件类型;设置Content-Disposition触发下载(如果需要在线预览可调整为inline)。

注意事项

  • 需要确保OkHttp依赖已添加到项目中(Maven/Gradle)。
  • 要处理远程文件请求失败的情况,比如404、500等状态码,避免客户端收到错误响应。
  • 如果需要处理大文件,建议添加超时、断点续传等额外逻辑,根据业务需求扩展。

内容的提问来源于stack exchange,提问作者许基目

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 11:05:18