如何用 Java Spring/React 下载 XLSX 文件?
How to download XLSX file with Java Spring/React?
我正在尝试生成 .XLSX
文件并下载它。我正在使用 Apache POI
生成 excel 文件,我正在使用 Swagger UI
来测试端点。我一直在寻找几个小时,运气不佳。我用来生成 Excel 文件的代码是:
@GetMapping(path = "/download")
public ResponseEntity<ByteArrayResource> download(@RequestParam(name = "ids") long [] ids) {
// ... other code ...
XSSFWorkbook workbook = createWorkbook(reports);
LocalDate date = LocalDate.now();
String filename = "MYC " + date.getYear() + "." + date.getMonthValue();
try {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
HttpHeaders header = new HttpHeaders();
header.setContentType(new MediaType("application", "vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
header.set(HttpHeaders.CONTENT_DISPOSITION, String.format("attachment; filename=%s.xlsx", filename));
workbook.write(stream);
workbook.close();
return new ResponseEntity<>(new ByteArrayResource(stream.toByteArray()), header, HttpStatus.CREATED);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
在使用 Swagger UI
进行测试时,我进行了调用并在 return 中得到了这个:
我在 SO 上找到的一个答案建议使用 force-download
而不是 vnd.openxmlformats-officedocument.spreadsheetml.sheet
所以我继续尝试。这一次,Swagger UI
实际上生成了一个 Download file
link。我可以点击它,文件就可以下载了。但是使用 force-download
真的是合适的方法吗?
现在,我尝试在我的前端下载,无论我使用 force-download
还是 vnd.openxmlformats-officedocument.spreadsheetml.sheet
,我只得到一个 'corrupted' .xlsx
文件.
刚在写自己的问题时发现 SO 问题,这个人似乎也收到了相同类型的回复。他通过将二进制数据转换为字符串来修复它。不确定这是否也是我应该做的以及我将如何去做。
好的,所以我设法通过从多个 google 搜索中收集信息来解决这个问题。对于我的后端,我将 byte array
编码为 Base64
,然后将其作为 String
.
返回
@GetMapping(path = "/download")
public ResponseEntity<String> download(@RequestParam(name = "ids") long[] ids) {
// ... other code ...
XSSFWorkbook workbook = createWorkbook(reports);
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
HttpHeaders headers = new HttpHeaders();
headers.setContentType("text", "plain");
workbook.write(outputStream);
workbook.close();
return new ResponseEntity<>(Base64.getEncoder().encodeToString(outputStream.toByteArray(), headers, HttpStatus.OK);
} catch (IOException e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
在前端,我使用 atob() 解码 String
,然后解码为 ArrayBuffer
// ... other code ...
actions.getSpreadsheet(ids)
.then(result => {
var date = new Date();
var filename = "JSC " +
date.getFullYear() +
"." +
(date.getMonth() + 1);
var url = window.URL.createObjectURL(new Blob([this.s2ab(atob(result.data))], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;' }));
var a = document.createElement('a');
a.href = url;
a.download = filename + '.xlsx';
document.body.appendChild(a);
a.click();
a.remove();
}).catch(error => {
alert('Error retrieving report: ' + error);
})
s2ab = s => {
var buf = new ArrayBuffer(s.length);
var view = new Unit8Array(buf);
for (var i = 0; i != s.length; i++) {
view[i] = s.charCodeAt(i) & 0xFF;
}
return buf;
}
我正在尝试生成 .XLSX
文件并下载它。我正在使用 Apache POI
生成 excel 文件,我正在使用 Swagger UI
来测试端点。我一直在寻找几个小时,运气不佳。我用来生成 Excel 文件的代码是:
@GetMapping(path = "/download")
public ResponseEntity<ByteArrayResource> download(@RequestParam(name = "ids") long [] ids) {
// ... other code ...
XSSFWorkbook workbook = createWorkbook(reports);
LocalDate date = LocalDate.now();
String filename = "MYC " + date.getYear() + "." + date.getMonthValue();
try {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
HttpHeaders header = new HttpHeaders();
header.setContentType(new MediaType("application", "vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
header.set(HttpHeaders.CONTENT_DISPOSITION, String.format("attachment; filename=%s.xlsx", filename));
workbook.write(stream);
workbook.close();
return new ResponseEntity<>(new ByteArrayResource(stream.toByteArray()), header, HttpStatus.CREATED);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
在使用 Swagger UI
进行测试时,我进行了调用并在 return 中得到了这个:
我在 SO 上找到的一个答案建议使用 force-download
而不是 vnd.openxmlformats-officedocument.spreadsheetml.sheet
所以我继续尝试。这一次,Swagger UI
实际上生成了一个 Download file
link。我可以点击它,文件就可以下载了。但是使用 force-download
真的是合适的方法吗?
现在,我尝试在我的前端下载,无论我使用 force-download
还是 vnd.openxmlformats-officedocument.spreadsheetml.sheet
,我只得到一个 'corrupted' .xlsx
文件.
刚在写自己的问题时发现
好的,所以我设法通过从多个 google 搜索中收集信息来解决这个问题。对于我的后端,我将 byte array
编码为 Base64
,然后将其作为 String
.
@GetMapping(path = "/download")
public ResponseEntity<String> download(@RequestParam(name = "ids") long[] ids) {
// ... other code ...
XSSFWorkbook workbook = createWorkbook(reports);
try {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
HttpHeaders headers = new HttpHeaders();
headers.setContentType("text", "plain");
workbook.write(outputStream);
workbook.close();
return new ResponseEntity<>(Base64.getEncoder().encodeToString(outputStream.toByteArray(), headers, HttpStatus.OK);
} catch (IOException e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
在前端,我使用 atob() 解码 String
,然后解码为 ArrayBuffer
// ... other code ...
actions.getSpreadsheet(ids)
.then(result => {
var date = new Date();
var filename = "JSC " +
date.getFullYear() +
"." +
(date.getMonth() + 1);
var url = window.URL.createObjectURL(new Blob([this.s2ab(atob(result.data))], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;' }));
var a = document.createElement('a');
a.href = url;
a.download = filename + '.xlsx';
document.body.appendChild(a);
a.click();
a.remove();
}).catch(error => {
alert('Error retrieving report: ' + error);
})
s2ab = s => {
var buf = new ArrayBuffer(s.length);
var view = new Unit8Array(buf);
for (var i = 0; i != s.length; i++) {
view[i] = s.charCodeAt(i) & 0xFF;
}
return buf;
}