2

I am using ModelAndView pattern to return excel representation of data that is generated in the Controller using Apache POI library.

However the excel gets corrupted(special characters are replaced with ?) when it gets downloaded. If I write the excel to file before pushing it out on the HTTP response, then a valid excel is output.

Here is the controller code that pushes control to ModelAndView

Map<String, Object> model = new HashMap<String, Object>();
model.put(ExcelBusinessReportView.KEY_REPORT_DISPLAY_DATA, reportData);
model.put(ExcelBusinessReportView.KEY_REPORT_DATE, reportRequestDTO.getReportDateUTCAtMidnight());
return new ModelAndView("excelBusinessReportView", model);

And here is the view class

@Service(value = "excelBusinessReportView")
public class ExcelBusinessReportView extends AbstractXlsView {

public static final String KEY_REPORT_DISPLAY_DATA = "reportData";
public static final String KEY_REPORT_DATE = "reportDate";

private static final String MIME_TYPE_EXCEL = "application/ms-excel";
private static final String HEADER_VALUE_CONTENT_DISPOSITION = "attachment; filename=qup_report.xls";

private static final String[] SUMMARY_HEADERS = ........
private static final String[] DETAIL_HEADERS = ........

@Override
protected void buildExcelDocument(Map<String, Object> model, Workbook workbook, HttpServletRequest request,
        HttpServletResponse response) throws Exception {
    BusinessSlotReportResource reportDisplayData = (BusinessSlotReportResource) model.get(KEY_REPORT_DISPLAY_DATA);
    DateTime reportDate = (DateTime) model.get(KEY_REPORT_DATE);

    // Build excel document
    Sheet sheet = workbook.createSheet(reportDate.toString(CommonConstants.IST_DATE_FORMATTER_PATTERN));
    sheet.setDefaultColumnWidth((short) 12);
    Integer currentRow = 0;

    // Build summary data
    currentRow = this.buildSummaryData(workbook, sheet, reportDisplayData, currentRow);

    // Create margin rows
    sheet.createRow(currentRow++);
    sheet.createRow(currentRow++);

    // Build detail data
    this.buildDetailsData(workbook, sheet, reportDisplayData, currentRow);

    response.setContentType(MIME_TYPE_EXCEL);
    response.setHeader(HttpHeaders.CONTENT_DISPOSITION, HEADER_VALUE_CONTENT_DISPOSITION);
}

Content of excel when written to file in the view

–œ‡°±·;˛ˇ   ˛ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇRoot Entryˇˇˇˇˇˇˇˇ@Workbookˇˇˇˇˇˇˇˇˇˇˇˇ˛ˇˇˇ˝ˇˇˇ˛ˇˇˇ    ˛ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ 

 !"#$%&'()*+,-./0˛ˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇˇ  ”ÃA·∞¡‚\panilallewar                                  

Same part of the excel when downloaded


��ࡱ�;��  ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Root Entry��������@Workbook������������������������    �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� 

 !"#$%&'()*+,-./0��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������  ��A����\panilallewar     

Anil Allewar
  • 101
  • 2
  • 6
  • 1
    I tried disabling the `org.springframework.boot.web.filter.OrderedCharacterEncodingFilter` using FilterRegistrationBean to see if the encoding was a problem, but that didn't help. `o.s.b.w.servlet.FilterRegistrationBean : Filter orderedCharacterEncodingFilter was not registered (disabled)` – Anil Allewar Jul 02 '18 at 05:48

1 Answers1

0

Usually instead of putting the file in the model I write it directly in the response.

The following code is for xlsx format, but the concept is the same for previous versions of excel.

This endpoint is accepting a JSON which will be mapped to MyPojo.

@RequestMapping(value = "exportToExcel", method = RequestMethod.POST)
public @ResponseBody HttpEntity<byte[]> generateExcel(@Valid @RequestBody final MyPojo data) throws IOException {
    final File file = File.createTempFile("MyExcelReport", "xlsx");
    file.deleteOnExit();
    final Path path = file.toPath();
    try (final FileOutputStream fileOut = new FileOutputStream(file)) {
        try (final XSSFWorkbook workbook = new XSSFWorkbook()) {

            final XSSFSheet sheet = workbook.createSheet(SHEET_NAME);
            //fill your excel sheets

            workbook.write(fileOut);
            final byte[] byteArray = Files.readAllBytes(path);
            final HttpHeaders header = new HttpHeaders();
            header.setContentType(new MediaType("application", "vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
            header.set("Content-Disposition", "inline; filename=MyExcelReport.xlsx");
            header.setContentLength(byteArray.length);
            return new HttpEntity<>(byteArray, header);
        } catch (final Exception e) {
            LOG.error("Error during creation of excel report", e);
            throw e;
        } finally {
            if (path != null) {
                try {
                    Files.delete(path);
                } catch (final IOException e) {
                    LOG.error("Unable to delete file:" + path.toString(), e);
                }
            }
        }
    }
}

Also if you are using a frontend framework like angular you have to properly setup the response type (https://stackoverflow.com/a/52703842/3657208)

cisk
  • 589
  • 3
  • 13