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

从Java Servlet获取PDF后,Blob对象生成空PDF文件问题求助

问题:AEM Servlet返回PDF流,前端生成Blob后PDF为空

从AEM环境的Java Servlet获取到有效PDF文件,但前端用JavaScript创建Blob对象后,生成的PDF为空。接收的数据形态看似正常,但PDF无法正常显示。

Java端PDF流处理代码

private void streamPDF (final SlingHttpServletResponse response, final Resource pdfRes) throws IOException {
        String fileName = pdfRes.getPath().substring(pdfRes.getPath().lastIndexOf("/") + 1);

        response.setContentType("application/pdf");
        response.setHeader("Content-disposition", "attachment; filename=" + fileName);

        Asset asset = pdfRes.adaptTo(Asset.class);
        final InputStream in = asset.getOriginal().getStream();

        final OutputStream out = response.getOutputStream();

        IOUtils.copy(in, out);

        out.close();

        in.close();
    }

JavaScript端请求及Blob创建代码

sendServletDownload: function (title, path) {
        let url = "myurl.pdf";
        $.ajax({
           url: url,
           type: 'GET',
           data: {
               path: path
           },
           success: function (data) {
               var blob = new Blob([data], { type: 'application/pdf' });

               // Create an URL object for the Blob
               var url = window.URL.createObjectURL(blob);

               // Configure the download link with the Blob's URL and the filename
               var downloadLink = document.getElementById('downloadLink');
               downloadLink.href = url;

               downloadLink.download = title + '.pdf';

               // Simulate a click in the link to iniciate the download
               downloadLink.click();

               // Free the URL of the object when it's not necessary anymore
               window.URL.revokeObjectURL(url);
           }, error: function (XMLHttpRequest, textStatus, errorThrown) {
              console.log("Error: {}", errorThrown);
           },
            xhrFields: {
                responseType: 'arraybuffer' // Stablish responseType to 'arraybuffer'
            }
       });
    }

尝试过的base64解码代码

function base64ToArrayBuffer(data) {
    var binaryString = window.atob(data);
    var binaryLen = binaryString.length;
    var bytes = new Uint8Array(binaryLen);
    for (var i = 0; i < binaryLen; i++) {
        var ascii = binaryString.charCodeAt(i);
        bytes[i] = ascii;
    }
    return bytes;
};

解决方案

1. 修正Java端流处理逻辑

  • 确保输出流在复制完成后flush,避免缓冲区数据未写入响应:
    IOUtils.copy(in, out);
    out.flush(); // 新增flush操作
    out.close();
    in.close();
    
  • 添加Content-Length响应头,让前端明确数据大小:
    long contentLength = asset.getOriginal().getSize();
    response.setContentLengthLong(contentLength);
    
  • 改用try-with-resources自动管理流,避免手动关闭时的异常或遗漏:
    private void streamPDF (final SlingHttpServletResponse response, final Resource pdfRes) throws IOException {
        String fileName = pdfRes.getPath().substring(pdfRes.getPath().lastIndexOf("/") + 1);
    
        response.setContentType("application/pdf");
        response.setHeader("Content-disposition", "attachment; filename=" + fileName);
    
        Asset asset = pdfRes.adaptTo(Asset.class);
        try (InputStream in = asset.getOriginal().getStream();
             OutputStream out = response.getOutputStream()) {
            response.setContentLengthLong(asset.getOriginal().getSize());
            IOUtils.copy(in, out);
            out.flush();
        }
    }
    

2. 前端AJAX处理优化

  • 确认responseType: 'arraybuffer'生效,可改用原生XMLHttpRequest测试,避免jQuery潜在的参数覆盖问题:
    sendServletDownload: function (title, path) {
        let url = "myurl.pdf?path=" + encodeURIComponent(path);
        let xhr = new XMLHttpRequest();
        xhr.open('GET', url, true);
        xhr.responseType = 'arraybuffer';
        xhr.onload = function() {
            if (xhr.status === 200) {
                var blob = new Blob([xhr.response], { type: 'application/pdf' });
                var url = window.URL.createObjectURL(blob);
                var downloadLink = document.getElementById('downloadLink');
                downloadLink.href = url;
                downloadLink.download = title + '.pdf';
                downloadLink.click();
                window.URL.revokeObjectURL(url);
            }
        };
        xhr.send();
    }
    
  • 无需将arraybuffer类型数据转base64再解码,直接用原始响应数据创建Blob即可,转码会破坏二进制结构。

3. 排查响应头问题

  • 检查Servlet返回的响应头是否存在Transfer-Encoding: chunked,设置Content-Length后该头会被自动禁用,避免前端处理二进制数据异常。
  • 确认没有其他AEM过滤器或组件向响应流中添加额外字符,这会导致PDF文件损坏。

内容的提问来源于stack exchange,提问作者Daniel Culebras

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 22:43:19