为了账号安全,请及时绑定邮箱和手机立即绑定

下载期间出现 Spring Boot 异常导致空文件

下载期间出现 Spring Boot 异常导致空文件

有只小跳蛙 2023-06-21 16:11:48
请删除异常抛出前的注释以查看问题。路径是:http://localhost:8080/api/download原始问题: 我允许用户在 Angular7 应用程序中使用 JasperReports 下载报告,但问题仅与 Spring Boot 有关。报告生成有效,但我无法让文件下载按我的预期运行。目前:下载链接与 一起使用href,链接与 一起使用target="_blank"。用户单击它,浏览器会打开一个新选项卡(在后台)并弹出窗口File Save As。如果一切正常,则文件保存没有问题。但是如果在PDF生成过程中某处出现异常,浏览器仍然会弹出窗口File Save As并允许用户保存文件,它会完成,但文件将是0 bytes.应该是:当出现异常时,浏览器应该打开一个新选项卡,其中包含某种错误消息,但如果没有错误,则应该显示&ldquo;文件另存为&rdquo;窗口。代码:@GetMapping("/salary-report/{id}")public void generateSalaryReport(@PathVariable("id") long salaryReportId, HttpServletResponse response) throws IOException, JRException, SQLException {    JasperPrint jasperPrint;    var salaryReport = salaryReportRepositoryEx.findById(salaryReportId).orElseThrow(ResourceNotFoundException::new);    try (OutputStream out = response.getOutputStream()) {        HashMap<String, Object> parameters = new HashMap<>();        parameters.put("ReportId", salaryReport.getId());        // Set meta data        response.setContentType("application/x-download");        response.setHeader(            "Content-Disposition",            String.format("attachment; filename=\"%s%s-report%s-%s-%s.pdf\"",                .... parameters            )        );        // Set report        jasperPrint = salaryReportJasperReport.render(parameters); // exception usually here        JasperExportManager.exportReportToPdfStream(jasperPrint, out);    } catch (Exception e) {        // I tried changing the content type on Exception, but the same        response.setContentType("text/plain");        response.setHeader("Content-Disposition", null);        throw e;    }}带有链接的 HTML 代码 (Angular7):<td>    <a [href]="serverApiUrl+'/jasper/salary-report/'+salaryReport.id"       target="_blank"    >        PDF Download    </a></td>
查看完整描述

3 回答

?
饮歌长啸

TA贡献1951条经验 获得超3个赞

这个问题并不能完全解决。不允许HttpServletResponse在设置后删除任何标头,因此我必须在响应更改之前(之前response.setHeader("Content-Disposition",..)移动渲染。这允许正常抛出异常。

查看完整回答
反对 回复 2023-06-21
?
杨魅力

TA贡献1811条经验 获得超5个赞

问题是由于您没有以正确的方式处理异常,以便使用适合您的项目需求的正确方法。

这是一个可能的解决方案。

首先,您必须在您的方法中进行此更改。

   @GetMapping("/salary-report/{id}")

    public void generateSalaryReport(@PathVariable("id") long salaryReportId, HttpServletResponse response) throws IOException {

        JasperPrint jasperPrint;

        var salaryReport = salaryReportRepositoryEx.findById(salaryReportId).orElseThrow(ResourceNotFoundException::new);


        try (OutputStream out = response.getOutputStream()) {

            HashMap<String, Object> parameters = new HashMap<>();


            parameters.put("ReportId", salaryReport.getId());


            // Set meta data

            response.setContentType("application/x-download");

            response.setHeader(

                "Content-Disposition",

                String.format("attachment; filename=\"%s%s-report%s-%s-%s.pdf\"",

                    .... parameters

                )

            );


            // Set report

            jasperPrint = salaryReportJasperReport.render(parameters); // exception usually here

            JasperExportManager.exportReportToPdfStream(jasperPrint, out);

        } catch (Exception e) {        

            throw new IOException("Salary report generation failed for id: " + salaryReportId);

        }

    }

他们将此方法添加到您的控制器中。


@ExceptionHandler(IOException.class )

public ResponseEntity<String> handleAccessDeniedException(IOException ex) {

    //TODO Log your exception with a logging framework 

    return new ResponseEntity<String>(ex.getMessage, HttpStatus.INTERNAL_SERVER_ERROR);

 }


查看完整回答
反对 回复 2023-06-21
?
慕神8447489

TA贡献1780条经验 获得超1个赞

尝试将响应 http 状态代码设置为某些代码 4xx 或 5xx 可能是 (500),这应该有效。



查看完整回答
反对 回复 2023-06-21
  • 3 回答
  • 0 关注
  • 191 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信