我将帮你修改代码,直接将输入流返回给客户端,而不是保存到本地文件。以下是修改后的代码:
```java
@GetMapping("/downloadBilling")
public ResponseEntity downloadFile(@RequestParam("url") String downloadUrl) {
try {
URL url = new URL(downloadUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 获取输入流但不立即读取
InputStream inputStream = new BufferedInputStream(connection.getInputStream());
// 使用StreamingResponseBody实现流式传输
StreamingResponseBody responseBody = outputStream -> {
try (inputStream) {
byte[] buffer = new byte[1024 * 1024 * 5]; // 5MB缓冲区
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.flush();
} finally {
connection.disconnect();
}
};
// 设置响应头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
// 可以添加其他需要的响应头,如Content-Disposition
return new ResponseEntity<>(responseBody, headers, HttpStatus.OK);
} catch (Exception e) {
log.error("====download File failed====", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
```
主要修改点:
1. 改为返回`ResponseEntity`,支持流式传输
2. 使用`StreamingResponseBody`接口实现流式写入输出流
3. 移除了本地文件保存的逻辑
4. 添加了适当的响应头
5. 使用try-with-resources确保资源自动关闭
6. 添加了错误处理,返回500状态码
这种方法可以避免内存溢出问题,因为数据是流式传输的,不会一次性加载到内存中。
如果需要设置下载文件名,可以添加`Content-Disposition`响应头:
```java
headers.setContentDisposition(ContentDisposition.attachment().filename("filename.ext").build());
```