在Chrome的新标签页/窗口中打开使用jsPDF创建的pdf文件

3
我该如何使用javascript在Chrome 71中打开链接data:application/pdf;filename=generated.pdf;base64;DATA
从控制台打开链接成功,但从代码中打开失败。
由于安全原因,这段代码无法运行,仅供演示。
我看了一些类似的问题,但没有找到答案。

enter image description here

var button = document.getElementById("button");

button.addEventListener("click", generate, false);

function generate() {

  var doc = new jsPDF({
    orientation: "l",
    unit: "mm"
  });

  doc.text('ACT', 130, 20);
  var string = doc.output('datauristring');
  console.log(string);
  var link = document.createElement('a');
  link.href = string;
  link.setAttribute('target', '_blank');
document.body.appendChild(link);
  link.click();
  link.parentNode.removeChild(link);
}
<script src="https://unpkg.com/jspdf@1.5.3/dist/jspdf.min.js"></script>
<button id="button">Generate pdf table</button>


6个回答

10
尝试使用window.open()代替。以下代码对我有效。您需要修改窗口/页面大小。
let dataSrc = pdf.output("datauristring");
let win = window.open("", "myWindow");
win.document.write("<html><head><title>jsPDF</title></head><body><embed src=" + 
    dataSrc + "></embed></body></html>");

更新:

之前没有意识到 jsPDF 自带了一个方法pdf.output('dataurlnewwindow');,它使用了 iframe

pdf.output('dataurlnewwindow') 的缺点是它会打开一个新的标签页/窗口,以 datauristring 作为 PDF 文件名,并且下载按钮无法工作。而window.open(pdf.output('bloburl')) 看起来带有下载按钮并可以正常工作。

好的,PDF 文件可以像这样重命名:

pdf.setProperties({
    title: "jsPDF sample"
});

更新2:

为了避免页面在缩放时被截断,您可以相应地设置html2canvas的比例。


1
使用 pdf.output('dataurlnewwindow') 打开的 PDF,在地址栏中按下回车后也会消失,因为地址栏中没有 URL。而使用 window.open(pdf.output('bloburl')) 则不会有这个问题。 - Pavindu
2
我注意到在Chrome上使用pdf.output('dataurlnewwindow')时,新页面会继续加载。这使您无法使用下载功能。 但是在另一个浏览器(如Firefox)中,相同的方法没有这个问题。它可以按预期工作。 - Carsten

6

其实很简单,不要把事情复杂化。

window.open(URL.createObjectURL(doc.output("blob")))

或者更冗长但效率较低的版本:

let newWindow = window.open('/');
fetch(doc.output('datauristring')).then(res => res.blob()).then(blob => {
    newWindow.location = URL.createObjectURL(blob);
})

如果不是在onclick事件后立即打开新窗口,Chrome会阻止弹出窗口。这个解决方案并不好,因为会有一个从datauri到blob的不必要的转换。


2
是的,你也可以只使用 window.open(pdf.output('bloburl')); - Weihui Guo

3
这段代码对我来说是可行的。
  var doc = new jsPDF();
  doc.setProperties({
  title: "new Report"
  });
  doc.output('dataurlnewwindow');

0

我在本地机器上运行问题中的代码,出现以下错误:

不允许将顶部框架导航到数据URL:data:application/pdf;filename=generated.pdf;base64,...

JsPDF - 不允许将顶部框架导航到数据URL

我尝试了@WeihuiGuo的建议,但对我来说不起作用。

我发现Chrome自动打开pdf文件。

https://support.google.com/chrome/answer/6213030?hl=en
https://groups.google.com/a/chromium.org/forum/#!topic/chromium-bugs/z5hA0H6LFws

不仅仅是在新标签页中,当前页面也无法打开。
https://sphilee.github.io/jsPDF-CustomFonts-support/

在其他浏览器中,此页面可以正确显示。

这是一个令人沮丧的消息。


我现在有点难以理解你的目标是什么。如果你只想在新的标签页/窗口中打开你创建的jspdf pdf文件,那么它可以非常简单,只需要使用doc.output('dataurlnewwindow');即可。请查看我的更新答案。你得到的错误信息Not allowed to navigate top frame to data URL: data:application/pdf;filename=generated.pdf;base64,...更像是你试图在同一个标签页/窗口中打开pdf文件,而不是在新的标签页/窗口中。 - Weihui Guo
@WeihuiGuo,感谢您的耐心和帮助。我还没有找出原因,但是您的代码现在可以正常工作了pdf.output('dataurlnewwindow') - eustatos
没问题。但是答案不完美。我发现如果用户将页面放大到一定程度,输出可能会被剪切。我仍在努力寻找修复方法。 - Weihui Guo

-1

试一下这个...它会起作用的

var doc = new jsPDF({orientation: 'landscape',unit: 'mm',format: 'a4',putOnlyUsedFonts:true})
var burl = doc.output('bloburl');
console.log(burl)
var win = window.open(burl)
win.print()

2
欢迎来到SO!请不要发布仅包含代码的答案,而是添加一些文字说明您的方法如何运作以及它与其他给出答案的不同之处。您可以在我们的“如何撰写好答案”页面了解更多信息。 - ahuemmer

-1
你正在使用Javascript从原始数据生成PDF。为什么不使用像Adobe这样的阅读器来渲染它呢?当你从控制台点击链接时,这就是发生的事情。你只需要打开链接,它就会作为PDF文件打开。我认为你可能在过度复杂化这个任务。

感谢您的回复。在浏览器中打开PDF是业务需求。您可能知道情况(我可以下载PDF,但这并不适合客户)。 - eustatos
大多数浏览器仍然会使用已安装的阅读器在浏览器中打开它。我相信您仍然安装了某种PDF阅读器,当您在控制台中单击链接时,它就会打开。可能是Chrome内置了阅读器。尝试将链接复制/粘贴到地址栏中。您始终可以在iframe中打开链接,它将在浏览器中打开。如果您正在使用JavaScript库,则不确定是否从PDF创建HTML页面。 - Christopher Vickers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接