前端同事:“POST下载文件怎么接收?” 我:“???” 这问题,就像问“用筷子怎么喝汤”一样让人哭笑不得! 不过,既然有人问,那我就来当一回“科普达人”,给大家讲讲GET/POST下载文件的区别,保证让你听得津津有味,还能学到真本事!
// 前端:使用 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();
}
@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 请求下载文件
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);
});
}
@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对象?
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 方法适用场景:
POST 方法适用场景:
需要传递大量的参数或数据,如批量下载、认证信息等。
文件较大,或需要对文件内容进行特殊处理(例如压缩多个文件、加密文件等)。
安全性要求高的场景。
还记得那个“用筷子喝汤”的比喻吗? 就像喝汤可以用勺子也可以用筷子,下载文件也可以用GET或者POST,关键是要选对“工具”!
所以,下次再遇到文件下载的需求,别再纠结用勺子还是筷子啦! 根据实际情况,选择合适的“工具”,才能优雅地“享用”你的文件大餐!
最后,友情提示: 千万别试图用GET下载一个比你家房子还大的文件,否则…… 你懂的!