最近再做个功能,需要实现excel模版下载。在这里记录一下。
后端java实现
@PostMapping("/download")
public ResponseEntity<?> downloadTemplate(@RequestBody Map<String,String> templateTypeMap) {
String fileName = DownloadTemplateEnum.getTemplateNameByType(templateTypeMap.getOrDefault("templateType", null));
try {
// 创建文件资源
String filePath = "excelTemplate/" + fileName;
Resource resource = new ClassPathResource(filePath);
// 检查文件是否存在
if (!resource.exists()) {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body("文件不存在: " + fileName);
}
// 设置响应头
HttpHeaders headers = new HttpHeaders();
String encodedFileName = URLEncoder.encode(resource.getFilename(), StandardCharsets.UTF_8.toString());
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + encodedFileName + ".xlsx");
// 返回文件
return ResponseEntity.ok()
.headers(headers)
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(resource);
} catch (IOException e) {
// 处理其他异常
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("发生错误: " + e.getMessage());
}
}
- 这里使用了ClassPathResource用于读取resources目录下的模版文件。
- 使用ResponseEntity作为响应数据。如果在前端定义的有自己的封装响应数据结果,比如code和data,需要在这个结构中增加status。因为ResponseEntity响应的状态码在status中
declare interface IResponse<T = any> {
status: number
code: number
data: T extends any ? T : T & any
}
提示: 在使用ClassPathResource判断文件是否存在是,如果遇到明明文件已有,但是判断仍是false。检查编译后的target/classes/excelTemplate文件下是否有对应文件。很有可能是编译的时候没有把文件编译过去,重新编译或者重启idea或自己手动复制过去都可以解决
前端js实现
const handleDownload = async () => {
const data = { templateType: 'xxx' }
const response = await downloadTemplateApi(data, 'blob')
// 检查响应是否成功
if (response.status === 200) {
// 创建一个隐藏的 a 标签来触发下载
const link = document.createElement('a')
link.href = URL.createObjectURL(response.data)
link.download = '导入品牌模版.xlsx' // 设置下载的文件名
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
importManufacturerDialogVisible.value = !importManufacturerDialogVisible.value
} else {
ElMessage.error('下载失败')
}
}
- 传入参数的时候需要指定responseType为
blob类型 - 通过创建临时隐藏标签
扩展
前端常见的返回类型如下:
-
'arraybuffer':- 二进制数据的数组形式。
- 适用于需要处理二进制数据的情况,例如图像、音频或视频文件。
- 返回值是一个
ArrayBuffer对象。
-
'blob':- 二进制大对象(Binary Large Object)。
- 适用于需要处理二进制数据的情况,但与
arraybuffer不同的是,blob可以表示任何类型的二进制数据,并且可以被浏览器直接使用(例如显示为图片)。 - 返回值是一个
Blob对象。
-
'document':- 适用于需要将响应解析为 HTML 或 XML 文档的情况。
- 返回值是一个
Document对象,可以使用 DOM 操作方法进行处理。 - 通常用于处理 XML 数据或动态生成的 HTML 内容。
-
'json':- 将响应体解析为 JSON 格式。
- 适用于返回 JSON 数据的 API。
- 返回值是一个 JavaScript 对象。
-
'text':- 将响应体作为纯文本字符串处理。
- 适用于返回纯文本数据的 API。
- 返回值是一个字符串。
-
'stream':- 流式处理响应数据。
- 适用于处理大文件或需要逐步处理数据的情况。
- 返回值是一个可读流(ReadableStream)。
-
'formdata':- 将响应体解析为
FormData对象。 - 适用于处理表单数据。
- 返回值是一个
FormData对象,可以方便地访问和操作表单字段。
- 将响应体解析为