Java HttpServer大文件传输异常求助:客户端无法下载1GB文件
大文件下载失败的解决方案
问题根源
你的代码通过Files.readAllBytes()把1GB的文件一次性加载到内存中,这会触发两个核心问题:
- 内存占用急剧飙升,轻则引发GC频繁卡顿,重则直接抛出
OutOfMemoryError; - 浏览器需要等待服务器完全加载文件后才开始接收数据,等待时间过长会导致连接超时中断。
修复代码
修改APIHandler的handle方法,改用流式分块传输,避免一次性加载整个文件到内存:
package org.org.APIServer.api; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetSocketAddress; import java.nio.file.Files; import java.nio.file.Path; public class APIServer { public static void startAPIServer() { try { HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0); server.createContext("/api", new APIHandler()); server.setExecutor(null); server.start(); } catch (IOException e) { throw new RuntimeException(e); } } static class APIHandler implements HttpHandler { @Override public void handle(HttpExchange t) throws IOException { Path filePath = Path.of("pack.zip"); // 设置响应头,明确这是可下载的二进制文件 t.getResponseHeaders().set("Content-Type", "application/octet-stream"); t.getResponseHeaders().set("Content-Disposition", "attachment; filename=\"pack.zip\""); // 告知客户端文件总大小 long fileSize = Files.size(filePath); t.sendResponseHeaders(200, fileSize); // 分块读写文件,每次仅加载8KB数据到内存 try (InputStream in = Files.newInputStream(filePath); OutputStream out = t.getResponseBody()) { byte[] buffer = new byte[8192]; int bytesRead; while ((bytesRead = in.read(buffer)) != -1) { out.write(buffer, 0, bytesRead); out.flush(); // 确保数据及时发送给客户端,避免连接超时 } } // try-with-resources会自动关闭流,无需手动调用close } } }
关键优化点说明
- 流式传输:用8KB缓冲区分块读取文件,内存占用始终保持在极低水平;
- Content-Disposition头:告诉浏览器将响应作为附件下载,避免浏览器尝试解析二进制内容;
- 自动资源管理:
try-with-resources语法确保流资源正确关闭,避免泄漏; - 即时刷新输出流:每次写入后立即flush,让客户端及时接收数据,防止连接因长时间无响应中断。
可选进阶优化
如果需要支持断点续传(用户中途中断后可恢复下载),可以处理HTTP的Range请求头,返回对应区间的文件内容,但上述修改已经能解决当前1GB文件无法下载的问题。
内容的提问来源于stack exchange,提问作者boomcreeper11
相关产品推荐
相关产品推荐

