@TOC
前言
前端同事:“POST下载文件怎么接收?” 我:“???” 这问题,就像问“用筷子怎么喝汤”一样让人哭笑不得! 不过,既然有人问,那我就来当一回“科普达人”,给大家讲讲GET/POST下载文件的区别,保证让你听得津津有味,还能学到真本事!
一、GET下载文件:简单直接,但并非万能
- 使用场景:GET方法一般用于请求数据时,适用于通过URL直接传递下载的文件标识(如文件ID、文件名等)。如果文件本身比较小,并且参数量不大,使用GET方法通常是合适的。
- 优点:方法简单,适合一些简单的文件下载,浏览器通常也会直接支持GET请求的文件下载。
- 缺点:请求URL长度有限制,不能传输过多的参数,安全性低。如果下载的文件需要传递复杂的请求参数(如多个ID),POST可能会更加合适。
1.1 前端示例代码
// 前端:使用 GET 请求下载文件
function downloadFile() {
const fileId = "5356ad47a3754d56a1929e6224aa2fac";
const url = `/manage/downloadFile?id=${fileId}`; // 通过URL传递文件ID
const link = document.createElement('a');
link.href = url;
link.download = "temp.zip"; // 设置默认的下载文件名
link.click();
}
1.2 后端示例代码
@GetMapping("/downloadFile")
public ResponseEntity<Resource> downloadFile(@RequestParam String id) {
// 根据文件ID获取文件路径
String filePath = getFilePathById(id);
File file = new File(filePath);
if (!file.exists()) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "File not found");
}
// 设置响应头
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + file.getName());
headers.add(HttpHeaders.CONTENT_TYPE, "application/zip");
Resource resource = new FileSystemResource(file);
return new ResponseEntity<>(resource, headers, HttpStatus.OK);
}
二、POST下载文件:低调奢华,暗藏玄机
- 使用场景:POST方法适用于文件下载时,参数较多或需要发送较复杂的数据(如文件ID、用户认证信息等)。POST请求没有URL长度限制,适合传递大量参数或大数据量。
- 优点:POST方法可以通过请求体发送大量数据,适合多参数的复杂查询,安全性较高。且可以通过请求头传递额外的认证信息或自定义参数。
- 缺点:通常情况下,文件下载使用POST方法略显复杂,但如果你的需求涉及到传递很多数据或需要隐式传输参数,POST可能更适合
1.1 前端示例代码
// 前端:使用 POST 请求下载文件
function downloadFiles() {
const params = {
ids: ["5356ad47a3754d56a1929e6224aa2fac", "5356ad47a3754d56a1929e6224aa2faq"]
};
axios.post('/manage/batchDownload', params, { responseType: 'blob' })
.then((res) => {
// 创建一个Blob对象,并用URL.createObjectURL生成下载链接
const blob = res;
if(blob && blob instanceof Blob) {
const link = document.createElement('a');
const filename = `${Date.now()}_temp.zip`;
const url = window.URL.createObjectURL(blob);
link.href = url;
link.download = filename;
link.click();
window.URL.revokeObjectURL(url);
} else {
console.error('下载文件失败: 响应不是有效的Blob类型');
}
})
.catch((error) => {
console.error('下载文件失败:', error);
});
}
1.2 后端示例代码
@PostMapping("/batchDownload")
public void batchDownload(@RequestBody ContractIdsV2RequestDto params, HttpServletResponse response, HttpServletResponse response) throws IOException {
List<ContractFileInfo> fileInfoList = getFileInfoList(params.getIds());
// 设置响应头
String filename = "files.zip";
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=" + filename);
// 使用 ZipOutputStream 写入文件
try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
for (ContractFileInfo fileInfo : fileInfoList) {
String filePath = fileInfo.getFilePath();
if (StringUtils.isNotBlank(filePath)) {
try (InputStream inputStream = new FileInputStream(filePath)) {
ZipEntry zipEntry = new ZipEntry(fileInfo.getFileName());
zipOut.putNextEntry(zipEntry);
IOUtils.copy(inputStream, zipOut);
zipOut.closeEntry();
}
}
}
}
}
如何校验是否正确返回Blob对象?
- 打开浏览器的开发者工具(通常是按F12或Ctrl+Shift+I),切换到“Network”选项卡。
- 找到你的批量下载请求,查看响应内容
- 如果你看到的响应数据以PK(ZIP文件的头部标识)开头,那就说明后端返回了正确的ZIP文件。 如果不是,可能是后端返回了错误信息或其他内容,导致ZIP文件没有正确生成或传输。
POST请求的方法,无非就是后端处理文件之后,返回二进制数据,前端接受二进制数据从而转换下载,前端需要设置响应头为Blob:
responseType: 'blob' // 设置返回类型为Blob对象,就是二进制数据
然后前端将Blob对象转为一个临时的URL,就可以通过浏览器来下载了。
// 创建一个Blob对象,并用URL.createObjectURL生成下载链接
const blob = res // 接收到后端返回的二进制数据;
if(blob && blob instanceof Blob) {
const link = document.createElement('a');
const filename = `${Date.now()}_temp.zip`;
const url = window.URL.createObjectURL(blob);
link.href = url;
link.download = filename;
link.click();
window.URL.revokeObjectURL(url);
} else {
console.error('下载文件失败: 响应不是有效的Blob类型');
}
三、GET vs POST:如何选择?
GET 方法适用场景:
- 文件ID、文件名等参数较少且可以通过URL传递。
- 文件较小,不需要传递大量数据或复杂的认证信息。
- 安全性要求不高的场景。
POST 方法适用场景:
-
需要传递大量的参数或数据,如批量下载、认证信息等。
-
文件较大,或需要对文件内容进行特殊处理(例如压缩多个文件、加密文件等)。
-
安全性要求高的场景。
总结
还记得那个“用筷子喝汤”的比喻吗? 就像喝汤可以用勺子也可以用筷子,下载文件也可以用GET或者POST,关键是要选对“工具”!
- GET 就像勺子,简单直接,舀起汤来毫不费力,但遇到“大块头”就有点力不从心。
- POST 就像筷子,虽然上手难度高一点,但夹起“大块头”来游刃有余,还能玩出各种花样。
所以,下次再遇到文件下载的需求,别再纠结用勺子还是筷子啦! 根据实际情况,选择合适的“工具”,才能优雅地“享用”你的文件大餐!
最后,友情提示: 千万别试图用GET下载一个比你家房子还大的文件,否则…… 你懂的! 😉