You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot接口PDF下载失败问题排查求助

Spring Boot PDF下载接口问题排查与修复

你的Controller代码存在几个潜在问题,可能导致下载失败:

  • 文件名未编码:直接拼接CPF作为文件名,若包含.、-这类特殊字符,部分浏览器可能无法正确解析文件名,进而影响下载流程。
  • InputStreamResource的局限性:ByteArrayInputStream包装成InputStreamResource后,Spring无法自动获取文件长度,浏览器无法确认文件大小,可能中断下载。
  • 异常状态码错误:生成PDF失败属于服务端内部错误,返回400 Bad Request不符合HTTP规范,应返回500 Internal Server Error。

修改后的代码:

@RestController
@RequestMapping("/api/pdf")
public class PdfController {

    private final PdfService pdfService;

    public PdfController(PdfService pdfService) {
        this.pdfService = pdfService;
    }

    @PostMapping("/generate")
    public ResponseEntity<ByteArrayResource> createPdf(@RequestBody PendenciasModel pendenciasModel) throws IOException {
        try {
            ByteArrayInputStream bis = pdfService.createPdf(pendenciasModel);
            byte[] pdfBytes = bis.readAllBytes();
            ByteArrayResource resource = new ByteArrayResource(pdfBytes);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_PDF);
            // 按RFC规范编码文件名,兼容特殊字符
            String encodedFilename = URLEncoder.encode(pendenciasModel.getClient().getCpf() + ".pdf", StandardCharsets.UTF_8);
            headers.setContentDisposition(ContentDisposition.attachment()
                    .filename(encodedFilename, StandardCharsets.UTF_8)
                    .build());
            headers.setContentLength(pdfBytes.length);

            return ResponseEntity.ok()
                    .headers(headers)
                    .body(resource);
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
        }
    }
}

额外检查项:

  1. 确认pdfService.createPdf()返回的ByteArrayInputStream未被提前读取(若流指针已到末尾,响应内容为空)。
  2. 前端调用时需设置响应类型为blob,避免框架默认将响应解析为JSON:
    // 以axios为例
    axios.post('/api/pdf/generate', requestData, { responseType: 'blob' })
      .then(res => {
        const url = window.URL.createObjectURL(new Blob([res.data]));
        const a = document.createElement('a');
        a.href = url;
        a.download = res.headers['content-disposition'].split('filename=')[1];
        document.body.appendChild(a);
        a.click();
        window.URL.revokeObjectURL(url);
        a.remove();
      });
    

内容的提问来源于stack exchange,提问作者Michel Lopes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 11:30:14