简体   繁体   中英

Downloaded Xlsx file with spring mvc is corrupted and content-type is changed

Controller method which call a service and generate xlsx using apache-poi and return a view.

@RequestMapping(value = "/getSummary", method = RequestMethod.GET)
public String getSummary(Model model, HttpServletRequest request,
                                             HttpServletResponse response,
                                             @ModelAttribute("dateFrom") String dateFrom,
                                             @ModelAttribute("dateTo") String dateTo) throws Exception {

    logger.debug("date=" + dateFrom + "TO date=" + dateTo);
    AuthParam authParam = (AuthParam) request.getSession().getAttribute("authParam");
    if (authParam == null) {
        model.addAttribute("success", false);
        model.addAttribute("error_msg", "Auth Failed.");
        return "shipment/getSummary";
    }
    try {
        List<SummaryResponse> summaryBeanResponse = reportClient.getSummary(authParam, dateFrom, dateTo);
        logger.debug("Result List Size : {}", summaryBeanResponse.size());
        if (summaryBeanResponse.size() > 0) {
            byte[] reportBytes = buildSummaryXlsx(summaryBeanResponse, dateTo);
            logger.debug("Xlsx Sheet Generated!!");
            String fileName = "summary_" + StringUtils.join(dateTo.split("-"), "_") + ".xlsx";
            model.addAttribute("success", true);
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("content-disposition", "attachment; filename=" + fileName);
            logger.debug("Content-Type : {}", response.getContentType());
            logger.debug("Header : {}", response.getHeader("Content-Disposition"));
            response.getOutputStream().write(reportBytes);
            logger.debug("Set ALL");
        } else {
            model.addAttribute("success", false);
            model.addAttribute("error_msg", "No data found by search.");
        }
    } catch (Exception ex) {
        model.addAttribute("success", false);
        model.addAttribute("error_msg", "Service error.");
        logger.error("ERROR on report xlsx", ex);
    }
    return "shipment/getSummary";
}

private byte[] buildSummaryXlsx(List<SummaryResponse> summaryResponseList, String date) throws Exception {
    try {
        Workbook workbook = new XSSFWorkbook();
        // create excel xls sheet
        XSSFSheet sheet = (XSSFSheet) workbook.createSheet("summary");
        sheet.setDefaultColumnWidth(14);

        // create style for header cells
        XSSFCellStyle headerStyle = (XSSFCellStyle) workbook.createCellStyle();
        Font font = workbook.createFont();
        font.setFontName("Arial");
        headerStyle.setFont(font);
        headerStyle.setAlignment(HorizontalAlignment.CENTER);
        headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);

        int rowCount = 0;
        int cellCount = 0;

        // Manipulating Data Using Apache-POI

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        workbook.write(byteArrayOutputStream);
        return byteArrayOutputStream.toByteArray();
    } catch (Exception ex) {
        logger.debug("Exception On Population Xlsx Sheet, {}", ex);
    }
    return null;
}

this is the jsp view name getSummary.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Get Xlsx report</title>
    <script type="text/javascript">
        $(document).ready(function () {
            var isSuccess = ${success};
            if (isSuccess == false) {
                var msg = "${error_msg}";
                alertify.alert(msg, function() {
                    window.location = "<%= request.getContextPath() %>/shipment/view.html";
                });
            }
        });
    </script>
</head>
<body>
${error_msg}
</body>
</html>

I am setting content-type but response header looks like

**Response Headers**
HTTP/1.1 200 OK
Cache-Control: no-cache
Cache-Control: no-store
Date: Mon, 31 Jul 2017 12:26:12 GMT
Pragma: no-cache
Transfer-Encoding: chunked
Content-Type: text/html;charset=UTF-8
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Content-Disposition: attachment; filename=summary_2017_07_31.xlsx
Set-Cookie: JSSESSIONID=1501503972634; path=/
Content-Language: en

Printed Log:

    2017-07-31 18:26:12,635 DEBUG [admin] (ShipmentController.java:522) - REPORT date=2017-07-1TO date=2017-07-31
    2017-07-31 18:26:12,635 DEBUG [admin] (ReportServiceClient.java:178) - Calling [ReportService.getSummary] service for dateFrom[2017-07-1] and dateTo[2017-07-31]
    2017-07-31 18:26:12,671 DEBUG [admin] (ShipmentController.java:531) - Result List Size : 4
    2017-07-31 18:26:12,824 DEBUG [admin] (ShipmentController.java:534) - Xlsx Sheet Generated!!
    2017-07-31 18:26:12,824 DEBUG [admin] (ShipmentController.java:539) - Content-Type : application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
    2017-07-31 18:26:12,824 DEBUG [admin] (ShipmentController.java:540) - Header : attachment; filename=summary_2017_07_31.xlsx
    2017-07-31 18:26:12,824 DEBUG [admin] (ShipmentController.java:542) - Set ALL

I can download the xlsx file but the data is corrupted. Actually the web page content/html page view is written in xlsx file.

when there is no data I want to show popup and when there is data I want to download the created xlsx.

Why content-type change after I am setting it. How can I properly solve this.

NB: I have a similar type of controller method where I create a pdf file and set the content type to response.setContentType("application/pdf") and it's working fine for me.

You need to add a separate controller @RequestMapping that only returns XLSX file bytes, annotated with @ResponseBody . You can then create a hyperlink to this endpoint from within they body of your JSP so that when the user clicks it, they can download the file. It will not work to attempt to return both the JSP body and the XLSX content in a single RequestMapping as the return type of the containing JSP is set to text/html .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM