相对于上传,下载时复杂的地方就是文件中文名称乱码
前端
<el-button @click="clickCall('handleExport', scope,index)">导出</el-button>
// 文件下载操作
handleExport(row) {
axios
.get(**********master/proj/exportContract?id=" + row.id, {
responseType: "blob",
headers: { Authorization: Cookie.get("**********") },
})
.then((response) => {
// 获取后端返回的文件名
const contentDisposition = response.headers["content-disposition"];
const fileNameMatch = contentDisposition.match(/filename="(.+)"/);
console.log(fileNameMatch[1])
const fileName = this.binaryStringToString(fileNameMatch[1])
// 创建URL并模拟点击下载链接
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement("a");
link.href = url;
link.setAttribute("download", fileName);
document.body.appendChild(link);
link.click();
})
.catch((err) => {
this.$message.error(`数据导出失败,${err.message}`);
});
},
binaryStringToString(binaryStr){
const binaryBytes = binaryStr.split(" ");
const bytes = binaryBytes.map(binaryByte => parseInt(binaryByte, 2));
const utf8String = new TextDecoder().decode(new Uint8Array(bytes));
return utf8String;
},
后端
@ApiOperation("导出合同文件")
@GetMapping("exportContract")
public ResponseEntity<Resource> exportData(@RequestParam(value="id")Integer id) throws Exception {
return projectService.exportData(id);
}
@Override
public ResponseEntity<Resource> exportData(Integer id) throws IOException {
Project project = projectRepo.getById(Long.valueOf(id));
if (project.getContactFile().isBlank()) {
throw (new BizExceptEntityNotFound("文件不存在!"));
}
File file = new File(project.getContactFile());
// 设置响应头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
String binaryString = stringToBinary(project.getContactFile().split("/")[2]);
System.out.println(project.getContactFile().split("/")[2]);
System.out.println(binaryString );
System.out.println(binaryToString(binaryString ));
headers.setContentDisposition(ContentDisposition.parse("attachment; filename=" +binaryString ));
return new ResponseEntity<>(new FileSystemResource(file), headers, HttpStatus.OK);
}
/**
* 字符串转8位一组的二进制字符串
* @param inputString
* @return
*/
public static String stringToBinary(String inputString) {
byte[] utf8Bytes = inputString.getBytes(StandardCharsets.UTF_8);
StringBuilder binaryStr = new StringBuilder();
for (byte b : utf8Bytes) {
String binaryByte = String.format("%8s", Integer.toBinaryString(b & 0xFF)).replace(' ', '0');
binaryStr.append(binaryByte).append(" ");
}
return binaryStr.toString().trim();
}
public static String binaryToString(String binaryStr) {
StringBuilder result = new StringBuilder();
String[] binaryBytes = binaryStr.split(" ");
byte[] bytes = new byte[binaryBytes.length];
for (int i = 0; i < binaryBytes.length; i++) {
bytes[i] = (byte) Integer.parseInt(binaryBytes[i], 2);
}
result.append(new String(bytes, StandardCharsets.UTF_8));
return result.toString();
}
我采用的是把文件名转成二进制传输,再转化回去。最后没乱