JDBC 本身不支持断点下载,实际是通过 Web 层解析 HTTP Range 请求,从数据库 BLOB 中流式读取指定字节范围并返回。需用 setBinaryStream 存储、getBinaryStream + skipFully 跳过前 N 字节,配合 206 响应头实现;推荐对象存储替代数据库存大文件。

Java 中 JDBC 本身不直接支持“断点下载”——它只是数据库访问接口,不处理 HTTP 协议或文件传输的断点续传逻辑。所谓“用 JDBC 实现文件断点下载”,实际是指:将文件以二进制形式(BLOB)存入数据库,再通过 Web 层(如 Servlet/Controller)配合 HTTP Range 请求,读取数据库中对应字节范围的数据,返回给客户端实现断点续传。
1. 数据库存储:用 BLOB 保存文件原始数据
建表时使用 BLOB 类型(MySQL)、BYTEA(PostgreSQL)或 BLOB(Oracle)。插入时用 PreparedStatement.setBinaryStream() 或 setBytes():
- 推荐用
setBinaryStream(int parameterIndex, InputStream input, long length),避免全量加载到内存 - 例如上传一个大 ZIP 文件时,可从
HttpServletRequest.getInputStream()直接流式写入
2. 查询指定字节范围:不能直接“查某段 BLOB”,需分步处理
JDBC 不支持 SQL 级别按偏移量读取 BLOB 片段(如 MySQL 的 SUBSTRING(blob_col, offset, len) 有局限且不可移植)。正确做法是:
- 先用普通查询获取完整 BLOB 的
InputStream(如ResultSet.getBinaryStream("file_data")) - 在 Java 层跳过前 N 字节(用
inputStream.skip(n)),再读取指定长度 -
注意:
skip()可能未跳满,需循环调用并检查返回值;更稳妥用org.apache.commons.io.IOUtils.skipFully()
3. Web 层响应 Range 请求:配合 HTTP 断点协议
客户端(如浏览器、wget、curl)发起带 Range: bytes=1024-2047 的 GET 请求,服务端需:
- 解析请求头中的
Range,提取 start/end(若无则返回完整文件,状态码 200) - 根据文件总大小(可存在数据库元数据表中,或查
BLOB.length(),但部分驱动不支持,建议单独存file_size字段)校验范围合法性 - 从数据库查出 BLOB 流 → 跳过
start字节 → 读取(end - start + 1)字节 → 写入响应输出流 - 设置响应头:
Status: 206 Partial Content、Content-Range: bytes start-end/total、Content-Length: (end-start+1)、Accept-Ranges: bytes
4. 注意事项与优化建议
-
不要把大文件全 load 到内存:避免
ResultSet.getBytes()或Blob.getBytes(),始终用流式读取(getBinaryStream()) -
连接和流必须及时关闭:尤其 BLOB 流依赖数据库连接,用 try-with-resources 包裹
Connection、PreparedStatement、ResultSet、InputStream - 考虑性能瓶颈:数据库不是文件服务器。频繁读取大 BLOB 会增加 DB I/O 和网络压力,生产环境建议改用对象存储(MinIO/OSS/S3),数据库只存路径和元数据
- 事务与长连接:BLOB 流读取期间连接保持打开,避免在长事务中操作,防止连接池耗尽
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











