AngularJS-Spring-查询结果为空时返回状态码和文本

时间:2019-05-01 11:49:23

标签: angularjs spring spring-boot

我有一个向Spring Boot应用程序请求的AngularJS项目。

然后,Spring Boot应用程序将返回以字节为单位的数据,以后可以将其下载为Excel文件,如下所示:

Spring Boot控制器应用程序:

public ResponseEntity generateExcelReport(@RequestBody ArrayList<SearchCriteria> searchCriteriaList) {
    Query dynamicQuery = new Query();

    HttpHeaders responseHeaders = new HttpHeaders();
    responseHeaders.add("Content-Disposition", "attachment");

    try {
        List<Investment> resultList = investmentService.findByDynamicQuery(dynamicQuery);

        Workbook workbook = myService.generateExcelReport(resultList);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        workbook.write(out);

        byte[] bArray = out.toByteArray();
        ByteArrayResource resource = new ByteArrayResource(bArray);

        workbook.close();
        out.close();
        out.flush();

        return ResponseEntity
            .ok()
            .headers(responseHeaders)
            .contentLength(resource.getByteArray().length)
            .contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
            .body(resource);
    } catch (IOException e) {
        return ResponseEntity.badRequest().body(e);
    }
}

但是我想通过改善ResponseEntity为空的情况下返回状态为resultList的{​​{1}}来改进此代码:

更新:

    public ResponseEntity generateExcelReport(@RequestBody ArrayList < SearchCriteria > searchCriteriaList) {
    Query dynamicQuery = new Query();

    HttpHeaders responseHeaders = new HttpHeaders();
    responseHeaders.add("Content-Disposition", "attachment");

    try {
        List < Investment > resultList = investmentService.findByDynamicQuery(dynamicQuery);

        // If there are no results found, throw a 204 No Content back to front-end
        // So that there is no Excel generation involved.
        if (resultList.isEmpty()) {
            return ResponseEntity.status(HttpStatus.NO_CONTENT).body("There are no results found.");
        }

        ...

        return ResponseEntity
            .ok()
            .headers(responseHeaders)
            .contentLength(resource.getByteArray().length)
            .contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
            .body(resource);
    } catch (IOException e) {
        return ResponseEntity.badRequest().body(e);
    }
}

这是前端的AngularJS代码段

ReportService.generateExcelReport($scope.searchCriteriaList)
.then(function (responseObj) {
    if (responseObj.status === 204) {
        return SweetAlert.swal("No results", responseObj.data, "warning");
    } 

    // responseObj.data = Excel bytes returned by Spring in this case
    var blob = new Blob([responseObj.data], {
        type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
    });

    FileSaver.saveAs(blob, "myreport.xlsx");

    swal.close();
})

但是我的问题是,我的$ http.post请求包含一个responseType: "arraybuffer"作为请求的一部分。

因此,  即使我在后端这样返回String:

return ResponseEntity.status(HttpStatus.NO_CONTENT).body("There are no results found.");

我仍然在响应数据中得到一个arraybuffer。而且我无法访问字符串。

$ http.post请求片段:

generateExcelReport: function (searchCriteriaList) {
    var requestConfig = {
        responseType: "arraybuffer",
        headers: {
            "Content-Disposition": "attachment"
        }
    };

    var url =  "my-api/generate-paiwi-reports-excel"

    return $http.post(url, searchCriteriaList, requestConfig);
}

我不确定我是否朝正确的方向前进。请帮忙。 =) 提前非常感谢您。 =)

1 个答案:

答案 0 :(得分:0)

我设法找到了一个解决方案,但是我不确定这是否是最合适的解决方案。

由于我仍然无法(无法想到)在我的responseType: "arraybuffer"请求中删除$http.post,因此我将始终有一个arraybuffer作为对控制器的响应。

即使我只是从Spring后端返回一个字符串,我也会有一个ArrayBuffer。

但值得庆幸的是,有一个名为TextDecoder的Web API可以解码我对字符串的ArrayBuffer响应。

我之所以发现这一点,是因为有一个关于SO的现有问题的回答。 Converting between strings and ArrayBuffers

这是我现在的全部代码:

春季后端;

List<Investment> resultList = investmentService.findByDynamicQuery(dynamicQuery);

// By throwing this HttpStatus, it will be in the .catch function of the Promise.
if (resultList.isEmpty()) {
    return ResponseEntity
        .status(HttpStatus.NOT_ACCEPTABLE)
        .body("There are no results found.");
}

AngularJS控制器:

// AngularJS $http.post request returns an httpPromise containing different properties        
ReportService.generateExcelReport($scope.searchCriteriaList)
.then(function(responseObj) {

    var dateToday = ReportService.getFullDateToday();
    var fileName = "MyReport_" + dateToday + ".xlsx";

    // responseObj.data = Excel bytes returned by Spring in this case
    var blob = new Blob([responseObj.data], {
        type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
    });

    FileSaver.saveAs(blob, fileName);

    swal.close();
})
.catch(function(error) {
    // I forced Spring to throw a 406 - Not Acceptable error when mongoDB query result is 0.
    if (error.status === 406) {
        var decoder = new TextDecoder("utf-8");
        var errorMessage = decoder.decode(error.data);

        return SweetAlert.swal("No Results", errorMessage, "warning");
    }

    console.error(error);
    SweetAlert.swal("Ooops!", "Something went wrong...", "error");
})