从Spring REST服务角度损坏Excel Blob

时间:2018-04-10 21:56:52

标签: java excel spring angular apache-poi

我目前正致力于通过Apache POI创建Excel的后端Spring REST服务,并且需要响应Angular Front-end。 Angular前端需要打开一个新窗口来显示/下载电子表格。

这是目前的后端方法:

    @GetMapping(value = "/api/path/{testValue}")
    public ResponseEntity<Object> downloadTestFile(@PathVariable(required = false, value = "testValue") int testValue) throws IOException {
        try {

            List<TestObject> testObjectList = testService.getObjectListList(testValue);

            Workbook responseExcel = testService.createExcel(testObjectList);

            ByteArrayOutputStream outStream = new ByteArrayOutputStream();  
            responseExcel.write(outStream);
            ByteArrayResource resource = new ByteArrayResource(outStream.toByteArray());

            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", "1.xls"));
            headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
            headers.add("Pragma", "no-cache");
            headers.add("Expires", "0");

            ResponseEntity<Object> responseEntity = ResponseEntity
                    .ok()
                    .headers(headers)
                    .contentType(MediaType.parseMediaType("application/octet-stream"))
                    .body(resource);
            return responseEntity;
        } catch (Exception e) {
            return new ResponseEntity<>("error occurred", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

我的测试前端Angular方法:

  var app = angular.module('testApp', []);
  app.controller('testCtrl', function($scope, $http) {
    $http.get("/api/path/12345")
    .then(function onSuccess(response) {
        var data = response.data;
        var blob = new Blob([data], {type: "application/vnd.ms-excel"});
        var objectUrl = URL.createObjectURL(blob);
        window.open(objectUrl);
    }, function onError(response) {
        //upload failed
        console.log('Error');
    });
});

出于某种原因,Excel因错误的名称而损坏,并且无法打开。我尝试了各种MIME类型。我还尝试从Excel手动保存电子表格并将其拉入InputStreamResource,但我得到的结果与通过Apache POI方法生成的结果相同。

知道什么是错的吗?

1 个答案:

答案 0 :(得分:0)

您可以尝试以下代码。

@GET
@Produces("application/vnd.ms-excel")
public Response getExcelFile(HttpServletRequest httpServletRequest) {

    List<TestObject> testObjectList = testService.getObjectListList(testValue);

    //list all columns
    String[] columns = {"col1", "col2"};

    Workbook wb = new XSSFWorkbook();
    Sheet sheet = wb.createSheet();

    // Create a Row
    Row hr = sheet.createRow(0);
    for (int c = 0; c < columns.length; c++) {
        Cell cell = hr.createCell(c);
        cell.setCellValue(columns[c]);
    }

    // Create Other rows and cells with data
    int rowNum = 1;

   for(TestObject obj : testObjectList){ 
      Row row = sheet.createRow(rowNum++);
      row.createCell(1).setCellValue(obj.getCol1());
      row.createCell(2).setCellValue(obj.getCol2());
   }

   // Resize all columns to fit the content size
    for (int i = 0; i < columns.length; i++) {
        sheet.autoSizeColumn(i);
    }
    // Now finally build response and send
    StreamingOutput streamOutput = new StreamingOutput() {
        @Override
        public void write(OutputStream out) throws IOException, 
        WebApplicationException {
            wb.write(out);
        }
    };
    javax.ws.rs.core.Response.ResponseBuilder response = Response.ok(streamOutput,
            "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    response.header("content-disposition", "attachment; filename=\"sample_download_file\".xlsx");
    return response.build();
}