我正在尝试为Spring引导应用程序编写xls下载。为了使用POI生成文件Iam。如果我直接从控制器下载文件而不将其传递到前端,则如下所示:
//Wrote this one just for testing if the file is already corrupt here.
FileOutputStream fos = new FileOutputStream("C:\\dev\\directDownload.xls");
fos.write(byteArray);
fos.flush();
fos.close();
}
工作正常,文件看起来像这样:
从后端下载xls而不将其传递给angular:
但这不是我的目标。我打算将Outputstream传递给我的角度组件。组件从服务类调用函数。此类从控制器获取响应,并将其传递回我的组件。在用户界面中,下载对话框打开。问题是下载的文件看起来像这样(通过excel或Open Office打开文件无关紧要):
当前xls:
我的Java控制器:
@CrossOrigin(exposedHeaders = "Content-Disposition")
@RequestMapping(value = "/report/file", produces = "application/vnd.ms-excel;charset=UTF-8")
public void getReportFile(@RequestParam(name = "projectNumber") final String projectNumber,
@RequestParam(name = "month") final int month, @RequestParam(name = "year") final int year,
@RequestParam(name = "employee") final int employee,
@RequestParam(name = "tsKey") final String tsKey,
final HttpServletResponse response) throws IOException {
response.setContentType("application/vnd.ms-excel;charset=UTF-8");
String excelFileName = "test.xls";
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment; filename=\"%s\"",
excelFileName);
response.setHeader(headerKey, headerValue);
//Here I create the workbook that I want to download
ProjectMonthReport report = reportService.getReport(projectNumber, month, year);
//ExcelService builts the workbook using POI
Workbook workbook = excelService.exportExcel(report, employee, tsKey);
//The response is stored in an outputstream
OutputStream out = response.getOutputStream();
response.setContentType("application/vnd.ms-excel");
byte[] byteArray = ((HSSFWorkbook)workbook).getBytes();
out.write(byteArray);
out.flush();
out.close();
//Wrote this one just for testing if the file is already corrupt here. --> It's fine.
FileOutputStream fos = new FileOutputStream("C:\\dev\\directDownload.xls");
fos.write(byteArray);
fos.flush();
fos.close();
}
使用POI构建文件的Java Service方法:
public Workbook exportExcel(final ProjectMonthReport report, final int employee, final String tsKey) throws IOException,
InvalidFormatException {
Workbook workbook = new HSSFWorkbook();
CreationHelper createHelper = workbook.getCreationHelper();
// Create a Sheet
Sheet sheet = workbook.createSheet("Employee");
// Create a Font for styling header cells
Font headerFont = workbook.createFont();
headerFont.setBold(true);
headerFont.setFontHeightInPoints((short) 14);
headerFont.setColor(IndexedColors.RED.getIndex());
// Create a CellStyle with the font
CellStyle headerCellStyle = workbook.createCellStyle();
headerCellStyle.setFont(headerFont);
Row headeRow = sheet.createRow(0);
Cell dateHeader = headeRow.createCell(0);
dateHeader.setCellValue("Datum");
Cell startHeader = headeRow.createCell(1);
startHeader.setCellValue("Beginn");
Cell endHeader = headeRow.createCell(2);
endHeader.setCellValue("Ende");
Cell activityHeader = headeRow.createCell(3);
activityHeader.setCellValue("Tätigkeitsbereit");
Cell cardHeader = headeRow.createCell(4);
cardHeader.setCellValue("Kartennummer");
List<WorkDescriptionDetail> details = report.getEmployees().get(employee).getKeyDetailMap().get(Integer.valueOf(tsKey)).getDetailList();
int counter = 1;
for (WorkDescriptionDetail detail : details) {
List <String> stringList= detail.toStringList();
Row row = sheet.createRow(counter);
Cell cellDate = row.createCell(0);
cellDate.setCellValue(stringList.get(0));
Cell cellStart = row.createCell(1);
cellStart.setCellValue(stringList.get(1));
Cell cellEnd = row.createCell(2);
cellEnd.setCellValue(stringList.get(2));
Cell cellActivity = row.createCell(3);
cellActivity.setCellValue(stringList.get(3));
counter ++;
}
return workbook;
}
我的角度分量:
saveFile(employee: string, tsKey:string) {
this.subscription = this.reportService.saveXlsFile(this.projectNumber, this.year, this.month, employee, tsKey)
.subscribe(response=> {
console.log(response);
let mediatype = 'application/vnd.ms-excel;charset=UTF-8';
const data = new Blob(["\ufeff",response.arrayBuffer()], {type: mediatype});
console.log(data);
saveAs(data, 'test.xls');
},
error => console.log("error downloading the file"));
}
Ts服务功能,称为:
saveXlsFile(projectNumber:string, year:string, month:string, empId: string, tsKey:string) {
let params:URLSearchParams = new URLSearchParams();
params.set('projectNumber', projectNumber);
console.log(projectNumber);
params.set('month', month);
console.log(month);
params.set( 'year', year);
console.log(year);
params.set('employee', empId);
console.log(empId);
params.set('tsKey', tsKey);
console.log(tsKey);
return this.http.get(this.baseUrl + "/file", { search: params } );
}
我试图通过Postman检索响应并直接下载文件。当我这样做时,Excel无法打开该文件(Excel刚刚崩溃了),但是我可以在OpenOffice版本中打开该文件,并且工作正常。它也没有损坏。
最近几天我一直在网上搜索,我认为这可能是前端引起的一个紧迫问题。但是也许这也是SpringBoot在这里扮演我的角色。有什么建议吗?
谢谢您的帮助!
答案 0 :(得分:0)
嘿,昨天我自己找到了解决此问题的方法。在角度服务中添加以下内容:
return this.http.get(this.baseUrl + "/file", { search: params, responseType: ResponseContentType.Blob }).map(
(res) => {
return new Blob([res.blob()], { type: 'application/vnd.ms-excel' });
});
之后,您需要像这样修改组件:
saveFile(employee: string, tsKey:string) {
this.subscription = this.reportService.saveXlsFile(this.projectNumber, this.year, this.month, employee, tsKey)
.subscribe(response=> {
console.log(response);
let mediatype = 'application/vnd.ms-excel';
saveAs(response, 'test.xlsx');
},
error => console.log("error downloading the file"));
}
所以问题在于我没有在响应中得到blob对象。...