jsPDF损坏PDF文件?

5
我正在尝试使用 jsPDF 利用 JavaScript 创建 PDF 文件。我有一个小测试页面。基本上,我有一个下载 PDF 按钮,它会从一个 span 中获取 base64 图像,并将其用于 imgData。然后我尝试将该图像数据addImage添加到 pdf 中,然后保存它。一切似乎都正常,它生成了 PDF 并提示进行下载。但是,当我尝试使用 xpdf 或 Foxit reader 查看 PDF 时,告诉我 PDF 文件已损坏。我是不是创建这个 PDF 的方式有误? 我的网页相当长,所以我把它放在了 Pastebin 上。
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />   
<script type="text/javascript" src="js/jquery/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="js/jquery/jquery-ui-1.8.17.custom.min.js"></script>
<script type="text/javascript" src="../jspdf.js"></script>
<script type="text/javascript" src="../libs/FileSaver.js/FileSaver.js"></script>
<script type="text/javascript" src="../libs/BlobBuilder.js/BlobBuilder.js"></script>
<script type="text/javascript" src="../jspdf.plugin.addimage.js"></script>
<script type="text/javascript" src="../jspdf.plugin.standard_fonts_metrics.js"></script>
<script type="text/javascript" src="../jspdf.plugin.split_text_to_size.js"></script>
<script type="text/javascript" src="../jspdf.plugin.from_html.js"></script>
<script type="text/javascript" src="js/basic.js"></script>
<title>Sup!</title>
<script>
function changeCan() {
  var c = document.getElementById("myCanvas");
  var ctx = c.getContext("2d");
  ctx.fillStyle="#FF0000";
  ctx.fillRect(0,0,128,128);
}
function changeCan3() {
  var c = document.getElementById("myCanvas");
  var ctx = c.getContext("2d");
  ctx.fillStyle="#FFFFFF";
  ctx.fillRect(0,0,128,128);
  var image = new Image();
  image.src = document.getElementById("3span").innerHTML;
  ctx.drawImage(image,0,0);
}
function changeCan4() {
  var imgData = document.getElementById("3span").innerHTML;
  window.alert(imgData.length);
  var doc = new jsPDF();
  doc.addImage(imgData, 'JPEG', 15, 40, 128, 128);
  doc.save('Test.pdf');
}
</script>
</head>
<body>
  Yo!<hr>
  <canvas id="myCanvas" width="128" height="128"></canvas><hr>
  <button type="button" onClick="changeCan()">Change Me To Red!</button>
  <button type="button" onClick="changeCan3()">Change Me To Span!</button>
  <button type="button" onClick="changeCan4()">Download Me!</button>
  <hr>
  <span id="3span" style="display:none;">B64 DATA HERE</span>
</body>
</html>

еңЁдҪ зҡ„3span DIVдёӯпјҢinnerHTMLеҢ…еҗ«data:image/jpeg;base64,гҖӮиҝҷжҳҜеҝ…йңҖзҡ„еҗ—пјҹеҸӘжҳҜдёҖдёӘжғіжі•пјҢжҲ‘дёҚзҹҘйҒ“иҝҷдёӘjsPDFеә“пјҢдҪҶжҲ‘еҫҲж„ҹе…ҙи¶ЈпјҢжҲ‘еҫҲеҝ«е°ұдјҡйңҖиҰҒе®ғ :) - JScoobyCed
好的,“data:image/jpeg;base64,”部分似乎是测试页面的另一部分所必需的,我在那里尝试将画布更改为笑脸人图像。此外,在jsPDF网页http://jspdf.com/上,猫图片的示例显示了“data:image/jpeg;base64,”的“头”,如果您愿意的话。@JScoobyCed,所以我不确定它是否需要,我可以快速尝试删除它并生成另一个PDF! - 0xhughes
@JScoobyCed 我快速从base64数据中删除了那一块信息,但是画布和PDF都出现了错误。我对画布不太担心,那只是为了好玩。但是PDF没有工作,这里是FireBug报错的信息,“getJpegSize无法找到图像的大小[在此错误上中断]throw new Error('getJpegSize could not find the size of the image');”我查看了他库中.js文件中的代码,但我无法确切地知道它在做什么。获取特定字符、获取长度并使用该信息进行一些数学运算。 - 0xhughes
我尝试了你的代码,但是PDF中生成的只有这个文本:[object Uint8Array]。所以我猜它不是损坏了,而是某些东西没有完全生成。我不能提供更多帮助,因为我需要先阅读关于jsPDF的资料,而现在无法做到。祝好运。 - JScoobyCed
嘿,谢谢你的尝试!那可能是警报,请多用一下以进行调试 :) 祝你未来好运。 - 0xhughes
我误读了你在@JScoobyCed的评论中尝试代码的内容,我看了PDF并明白了你在说什么。我可能只是在处理base64数据方面遗漏了一些东西或其他什么问题...当我弄清楚后,我会发布一个答案!希望你在考虑实现jsPDF时不会遇到太多麻烦 :) - 0xhughes
3个回答

6
我曾经遇到类似的问题,以下是我是如何解决的:使用Blob.jscanvas-toBlobFileSaver。我还注意到最新的BlobBuilder.min.js不正常工作,所以我改用了BlobBuilder.js。
var content = canvas.toDataURL('image/jpeg');
var doc = new jsPDF('landscape');
doc.addImage(content, 'JPEG', 0, 0);

var data = doc.output();
var buffer = new ArrayBuffer(data.length);
var array = new Uint8Array(buffer);

for (var i = 0; i < data.length; i++) {
    array[i] = data.charCodeAt(i);
}

var blob = new Blob(
    [array],
    {type: 'application/pdf', encoding: 'raw'}
);

saveAs(blob, filename);

非常简洁,下班后我会试一下!但有一个问题,在开始时您从画布中获取内容,在我的情况下,加载的图片来自本地机器(脚本生成网页和图像数据)。如果我已经在一个span中定义了DataURL,我能否简单地使用 "var content = getElementByID(“SPANID”).innerHtml" ?内部html是脚本生成的toDataURL ASCII。感谢您的好答案,我一定会研究您的方法并看看它的效果如何! - 0xhughes
我正在测试你的解决方案,但是我得到了一个名为name.pdf-1.part的PDF文件,有没有办法只获取name.pdf - Jefferson
我还没有找到去掉“.part”扩展名的方法。我认为我的FireFox版本(12)与jsPDF根本不兼容。我将FireFox升级到18.0.2版本,我的原始脚本可以工作了,但仍然有“.part”扩展名。我不确定为什么会这样,可能是库方面的问题。这很不幸,因为我想为我的网页提供一些跨浏览器的兼容性。我可能不得不设置我的客户端使用最新的FireFox。在jsPDF的github上提交了许多问题。也许我们会得到一个不错的更新! - 0xhughes
@Jeff 另外,我想添加一些通用信息。如果您想生成PDF文件,有一个网站上的文章介绍了一个人如何使用文本编辑器手动构建PDF文件。虽然我还没有尝试过,但是根据您的冒险精神和PDF的动态性,很可能可以在客户端创建自己的小函数来创建一些PDF文件。http://mariomalwareanalysis.blogspot.com/2012/02/how-to-manually-create-pdf.html 我还没有测试过他的方法,但如果您想要尝试冒险的话,这可能是一个好的开始 ;) - 0xhughes
那个.part扩展名真的很奇怪 :) 你在FF中使用任何扩展程序/插件进行下载吗?你能在Chrome中测试一下吗?你使用的是什么操作系统? - mtasic85
@mtasic85 不,我没有使用任何下载扩展程序,通常的方式就可以了,我使用Linux。 - Jefferson

2
我使用了1.3.4版本的jsPDF,它能正常工作。
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.4/jspdf.min.js"></script>

1

我曾经遇到类似的问题,使用 png 图片类型时,用 Adobe Reader 打开 PDF 文件会出现损坏。

将其改为 jpeg 类型解决了问题!

// Before : Corrupted PDF file when opened with Adobe Reader
var imgData = canvas.toDataURL('image/png');
var doc = new jsPDF('p', 'mm');
doc.addImage(imgData, 'png', 0, 0, 210, 295);

// After : Working
var imgData = canvas.toDataURL('image/jpeg');
var doc = new jsPDF('p', 'mm');
doc.addImage(imgData, 'jpeg', 0, 0, 210, 295);

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