首页 > 解决方案 > 在 A 元素的 HREF 中下载 PDF 会导致 PDF 为空

问题描述

我使用 a-element 作为之前必须使用 AJAX 查询的文件的下载按钮,如此此处此处所述。我将文件数据作为 Data-URI 放入 a 元素以创建下载按钮。不幸的是,我不能只指向文件,而是必须这样做。对于大多数下载格式的 HTML、CSV,它的工作方式如下:

var mimeType = "text/html"; // example. works also with others.
var BOM = '\ufeff';
var url = "data:"+ mimeType +";charset=UTF-8," + BOM + encodeURIComponent(response.data);
var linkElem = document.querySelector("#hiddenDownloadLink");
var link = angular.element(linkElem);
link.prop("href", url);
link.prop("download", 'myFile.' + extension);
linkElem.click();

好的。这样可行。但不适用于 PDF。

我在后端创建了一个 PDF(java,使用 openhtmltopdf,但我猜没关系,因为 PDF 绝对正确):

httpOutputMessage.getHeaders().add(HttpHeaders.CONTENT_TYPE, "application/pdf");
httpOutputMessage.getHeaders().add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"myFile.pdf\"");
makePdf(httpOutputMessage.getBody());

如果我直接查询后端,或者即使我将输出记录到文件中,一切都很好。但是当我如上所述使用我的下载控制器时,我得到了一个页数正确但完全为空的 PDF!我认为一定有编码问题。我尝试使用和不使用 BOM,也尝试使用或不使用 encodeURIComponent。

我还尝试使用 base64 解码作为。因为 window.atob(response.data) 由于换行等原因失败,所以我尝试了这种转换。结果是损坏的 PDF。导致 PDF 损坏。我不确定这是否有意义。

我的 PDF 数据是这样开始的,所以无论如何它都没有被压缩或编码:

%PDF-1.4
%����
1 0 obj
<<
/Type /Catalog
/Version /1.7
/Pages 2 0 R
>>
endobj
3 0 obj
<<

我还尝试将字节流转换为 blob 并生成此处此处所述的链接,但这会创建损坏的 PDF。

任何想法,为什么我得到空的 PDF 或者这里可能出了什么问题,我该如何重新下载下载链接?

-- 编辑 1

当我尝试时,我也会得到有效但空白的 PDF

var blob = new Blob([response.data], {type: 'application/pdf'});
var url = window.URL.createObjectURL(blob);
link.prop("href", url);

当我通过这个函数传递 response.data 时,我得到一个损坏的 PDF。

var utf8_to_b64 = function(str) {
  var unescape = window.unescape || window.decodeURI;
  str = encodeURIComponent(str);
  str = unescape(str);
  str = window.btoa(str);

  return str;
};

标签: javascriptpdfdata-uri

解决方案


所以我可以完全重现你的情况。我通过来自后端的 AJAX 请求加载并输出了一个 4 页的 PDF 文件,并通过您的代码示例得到了一个 4 页的空白 PDF。

这是我之后所做的(并获得了正确的 PDF 下载):

我对后端的输出进行了 base64 编码。就我而言,我使用的是 PHP,所以它是这样的:

$pdf = file_get_contents('test.pdf');
header('Content-Type: application/pdf');
echo base64_encode($pdf);

然后在前端我只改变了这一行:

var url = "data:"+ mimeType +";charset=UTF-8," + BOM + encodeURIComponent(response.data);

对此:

var url = "data:"+ mimeType +";base64," + encodeURIComponent(response.data);

希望这可以帮助。


推荐阅读