如何将HTML转换为PDF并通过Ajax POST以multipart/form-data格式发送
问题排查与解决方法
现有代码的核心问题
- 你生成PDF的逻辑本质是把HTML转成位图塞进PDF,本身就会出现模糊、排版错乱的问题,且你错误地将JPG图片的base64内容直接封装为PDF格式的Blob,生成的文件根本不是合法的PDF,上传到服务端自然无法正常识别。
- Ajax配置错误:手动设置了
multipart/form-data请求头却没有指定边界值,浏览器提交FormData时会自动生成带正确boundary的请求头,手动指定反而会导致请求格式错误。
修正方案
我们直接从jsPDF实例导出合法的PDF二进制流,不需要自己手动拼接Blob,同时可以用jsPDF内置的html方法直接渲染HTML内容,避免转图片导致的模糊问题,修正后的代码如下:
<script> var mywindow = window.open(); mywindow.document.write('<html><head><title>Convert to PDF</title>'); mywindow.document.write('</head><body >'); mywindow.document.write('<p>Convert this Page to PDF and send it to Ajax POST as Form</p>'); mywindow.document.write('</body></html>'); mywindow.document.close(); // 等待页面内容加载完成 mywindow.onload = function() { const doc = new jsPDF(); // 直接渲染HTML到PDF,不需要转图片,生成的是矢量内容,清晰度高 doc.html(mywindow.document.body, { callback: function (doc) { // 本地保存可选 doc.save('test.pdf'); // 直接从jsPDF获取PDF的Blob对象 const pdfBlob = doc.output('blob'); const form = new FormData(); form.append("file", pdfBlob, "FSM.pdf"); form.append("fileName", "FSM.pdf"); form.append("description", "12"); $.ajax({ "url": "my_URL", "method": "POST", "timeout": 0, // 删除手动设置的Content-Type,让浏览器自动处理FormData的边界 "processData": false, "contentType": false, "data": form, success: function(res) { console.log('上传成功', res); }, error: function(res) { console.log('上传失败', res); } }); }, x: 10, y: 10 }); } </script>
兼容性说明
如果你的jsPDF版本较低不支持html方法,仍然要使用html2canvas的话,可以调高html2canvas的缩放参数提升清晰度,然后同样从jsPDF实例导出Blob即可:
html2canvas(mywindow.document.body, { scale: 3, // 调高缩放比例提升图片清晰度 useCORS: true, onrendered: function(canvas) { const img = canvas.toDataURL("image/jpeg", 1.0); const doc = new jsPDF('p', 'mm', 'a4'); // 计算图片宽高适配A4纸尺寸,避免排版错乱 const imgWidth = 210; const pageHeight = 297; const imgHeight = canvas.height * imgWidth / canvas.width; let heightLeft = imgHeight; let position = 0; doc.addImage(img, 'JPEG', 0, position, imgWidth, imgHeight); heightLeft -= pageHeight; // 内容超过一页自动分页 while (heightLeft >= 0) { position = heightLeft - imgHeight; doc.addPage(); doc.addImage(img, 'JPEG', 0, position, imgWidth, imgHeight); heightLeft -= pageHeight; } doc.save('test.pdf'); const pdfBlob = doc.output('blob'); // 后续FormData和Ajax逻辑和上面方案一致即可 } });
内容的提问来源于stack exchange,提问作者user2644620
相关产品推荐
相关产品推荐

