Spring - 使用 POI 下载 excel

问题描述 投票:0回答:2

我有这个控制器,它创建一个空工作表,我想将 Excel 文件返回到导航器。问题是,Excel 文件已损坏。

如果我在计算机上创建该文件,该文件不会损坏,因此我的 HSSFWorkbook 是有效的。似乎是 spring 上下文添加的编码/封装问题?

@Controller
public class ExportController {

@RequestMapping(value = "/export/test/excel", method = RequestMethod.POST)
public void downloadExcelTestFile(
        HttpServletRequest request, 
        HttpServletResponse response) throws IOException {

    HSSFWorkbook wb = new HSSFWorkbook();

    wb.createSheet("Sheet1");

    //response.reset();
    //response.setStatus(HttpServletResponse.SC_OK);
    response.setContentType("application/vnd.ms-excel");
    response.setHeader("Content-Disposition", "attachment; filename=test.xls");

    OutputStream out = response.getOutputStream();
    wb.write(out); 

    out.flush();
    out.close();
    wb.close();
}

下载开始顺利,我收到文件 test.xls,但无法打开它。有没有一种 Spring 方法可以在 @Controller 内实现正确的下载?

我使用Spring 4.2.4

更新1

我尝试了 Spring 方式,但效果不佳

    HSSFWorkbook wb = new HSSFWorkbook();

    wb.createSheet("Sheet1");

    ByteArrayOutputStream bos = new ByteArrayOutputStream();

    try {
        wb.write(bos);
    } finally {
        bos.close();
    }

    byte[] bytes = bos.toByteArray();

    HttpHeaders headers = new HttpHeaders();

    headers.set("Content-Type", "application/vnd.ms-excel;");
    headers.set("content-length",Integer.toString(bytes.length));
    headers.set("Content-Disposition", "attachment; filename=test.xls");

    return  new ResponseEntity<byte[]>(bytes, headers, HttpStatus.CREATED);

更新3

我找到了原因,但我不明白为什么。

如果我构建我的 war 文件并在同一个 tomcat 7.0.70 中手动部署它,它就可以工作。我的 Excel 没有损坏。

如果我从eclipse中的开发环境下载,它不起作用。似乎是tomcat + eclipse的问题。

spring-mvc apache-poi
2个回答
0
投票

好吧,这不是 Spring 问题,甚至不是 tomcat 问题。

问题出在我的 grunt-connect-proxy 上,当我通过 localhost:9000 运行我的前端时:我下载的文件已损坏。如果我在 war 文件中构建项目或从 localhost:8080 (与服务器相同的端口)运行前端而无需“gruntserve”,因此无需代理即可工作。

我还没有解决 grunt 的问题...我只是忽略它,但这个答案可以节省你的时间。


0
投票

用于创建 Excel 并使用 Spring REST 返回它的示例 Spring 支持代码。输入参数可能会根据您的要求更改

@RequestMapping(value = "/convertFlatFileToExcel.do", method = RequestMethod.POST)
public HttpEntity<byte[]> convertFlatFileToExcel(@RequestParam(value="file") MultipartFile file,@RequestParam(value="jobid") String jobid) {
        ByteArrayOutputStream archivo = new ByteArrayOutputStream();
        XSSFWorkbook workbook = new XSSFWorkbook();
        workbook.write(archivo);
        if(null!=workbook && null!=archivo) {
            workbook.close();
                        archivo.close();
        }
    byte[] documentContent = archivo.toByteArray();
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
    headers.set(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"myexcelfile.xls\"");
    headers.setContentLength(documentContent.length);
    response = new ResponseEntity<byte[]>(documentContent, headers, HttpStatus.OK);
}

**示例用户界面代码: 下面是使用 Angular JS 调用 Rest Service 的示例代码。使用 https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2014-11-29/FileSaver.min.js 导入 FileSaver js 文件 这将使用 saveAs() 方法以给定名称保存给定的 excel blob 数据。 **

$http.post(urlBase+'/convertFlatFileToExcel.do', formData,{
                transformRequest : angular.identity,
                responseType: 'arraybuffer',
                headers : {
                    'Content-Type' : undefined,
                    'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
                }})
                .then(
                    function (response) {
                        $window.sessionStorage.showProgress = "";
                        var file = new Blob([response.data], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});
                        saveAs(file, jobid.toUpperCase()+'.xlsx');
                    },
                    function (errResponse) {
                        $window.sessionStorage.showProgress = "";
                        $mdDialog.show($mdDialog.alert({title: 'Invalid Job ID!',textContent: 'Please enter a valid Job ID. For any issues, please contact the admin!',ok: 'GOT IT!'}));
                        deferred.reject(errResponse);
                    });
© www.soinside.com 2019 - 2024. All rights reserved.