文件下载接口核心在于准确设置响应头、安全流式传输与严谨异常处理:必须设Content-Type和Content-Disposition(含filename),避免内存全加载,校验参数、路径与文件存在性,防范目录遍历。

文件下载接口的核心是把文件内容作为响应体返回,并通过响应头告诉浏览器“这是个要下载的文件”,而不是直接渲染。关键不在接口有多复杂,而在于头信息设置是否准确、流处理是否安全、类型判断是否合理。
明确HTTP方法与路径设计
下载接口通常用 GET 方法,路径带唯一标识,比如:
-
/files/{fileId}—— 按ID查数据库取文件元数据和二进制内容 -
/downloads/resume?name=report.pdf—— 按参数定位服务器本地文件
避免用 POST 做纯下载(不符合 REST 约定),除非业务强依赖请求体传参(如动态生成报表需 JSON 配置)。
正确设置响应头
两个响应头必不可少:
-
Content-Type:设为
application/octet-stream(通用二进制流),或更精确如application/pdf、image/jpeg。浏览器靠它识别内容类型 -
Content-Disposition:必须含
attachment; filename="xxx.pdf",否则可能被浏览器直接打开而非弹出保存框
注意中文文件名兼容性:IE/Edge 要 UTF-8 编码后 Base64 或 URL 编码;Firefox 接受 ISO-8859-1 编码转换;推荐统一用 URLEncoder.encode(filename, "UTF-8") 并加双引号包裹。
安全读取并写入响应流
不建议把整个文件加载进内存(尤其大文件),应边读边写:
- 从数据库读取
byte[]内容 → 直接写入response.getOutputStream() - 从磁盘读取
FileInputStream→ 用IOUtils.copy(in, out)或手动byte[8192]缓冲区循环读写 - 务必在
finally块中关闭输入流,但不要关闭 response.getOutputStream()(由容器管理)
若文件不存在,返回 HttpStatus.NOT_FOUND(404),别返回空流或错误页面。
服务端异常与边界处理
真实场景中容易忽略这些:
- ID 参数为空或非法格式 → 提前校验,返回 400
- 数据库查不到记录或文件物理路径不存在 → 返回 404,日志记录 ID 方便排查
- 读取文件时 IO 异常(如磁盘满、权限不足)→ 捕获
IOException,返回 500 并记录完整堆栈 - 敏感文件路径(如
../../etc/passwd)→ 对文件名做白名单校验或路径规范化限制,防止目录遍历
不复杂但容易忽略。


















