如何在单次请求中下载文件并强制浏览器自动保存到本地磁盘?
强制浏览器直接下载文件实现方案
要实现强制浏览器将文件直接保存到本地而非预览,核心是在HTTP响应中设置正确的响应头,你当前已完成文件上传逻辑,还需要新增配套的下载接口,具体实现如下:
现有上传代码修正
你当前的上传代码存在一处逻辑问题:存储文件时调用file.getName()获取的是前端上传表单的字段名,并非用户上传的源文件名,会导致后续下载时找不到对应文件,需要调整:
// 原错误代码 Path copyLocation = Paths.get(UPLOAD_DIR + File.separator + StringUtils.cleanPath(file.getName())); // 修改为 Path copyLocation = Paths.get(UPLOAD_DIR + File.separator + StringUtils.cleanPath(file.getOriginalFilename()));
下载接口实现
新增GET类型的下载接口,通过设置Content-Disposition响应头为attachment触发浏览器直接下载:
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @GetMapping("/downloadFile") public void downloadFile(@RequestParam String fileName, HttpServletResponse response) throws IOException { // 拼接目标文件的存储路径 Path targetPath = Paths.get(UPLOAD_DIR + File.separator + StringUtils.cleanPath(fileName)); File targetFile = targetPath.toFile(); // 校验文件存在性 if (!targetFile.exists()) { response.sendError(HttpServletResponse.SC_NOT_FOUND, "请求的文件不存在"); return; } // 配置响应头 强制触发下载 response.setContentType("application/octet-stream"); response.setContentLength((int) targetFile.length()); // 编码文件名,解决中文文件名乱码问题 String encodedName = URLEncoder.encode(fileName, StandardCharsets.UTF_8).replace("+", "%20"); response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + encodedName); // 将文件流写入响应 Files.copy(targetPath, response.getOutputStream()); response.flushBuffer(); }
注意事项
- 下载请求建议用GET方式,方便用户直接通过链接触发下载
- 需确保
UPLOAD_DIR对应的目录对应用进程有读写权限 - 若需要支持大文件下载,建议改用缓冲流分片写入,避免一次性加载全量文件到内存导致OOM
内容的提问来源于stack exchange,提问作者JavaGrot
相关产品推荐
相关产品推荐

