toPdf.ts
5.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import html2canvas from "html2canvas";
import jsPDF from "jspdf";
import { pdfToText } from "pdf-ts";
export async function htmlToPdf2(htmlCode: string) {
const container = document.createElement("div");
container.style.cssText = `
position: fixed;
left: -9999px;
top: -9999px;
width: 210mm; // 固定 A4 宽度
background: white;
`;
container.innerHTML = htmlCode;
document.body.appendChild(container);
try {
// 关键修改 1: 确保所有图片加载完成
await waitForImages(container);
// 关键修改 2: 强制触发布局计算
void container.offsetHeight;
const canvas = await html2canvas(container, {
scale: 2,
useCORS: true,
logging: true,
scrollY: -window.scrollY, // 消除滚动偏移
windowWidth: container.scrollWidth,
windowHeight: container.scrollHeight,
});
const pdf = new jsPDF("p", "mm", "a4");
const pageWidth = pdf.internal.pageSize.getWidth();
const imgRatio = canvas.width / canvas.height;
// 关键修改 3: 动态计算高度
const imgHeight = (pageWidth * canvas.height) / canvas.width;
pdf.addImage(
canvas.toDataURL("image/png"),
"PNG",
0,
0,
pageWidth,
imgHeight,
);
// 关键修改 4: 处理多页内容
if (imgHeight > pdf.internal.pageSize.getHeight()) {
pdf.addPage();
pdf.addImage(
canvas.toDataURL("image/png"),
"PNG",
0,
-pdf.internal.pageSize.getHeight(),
pageWidth,
imgHeight,
);
}
pdf.save("document.pdf");
} catch (error) {
console.error("生成失败:", error);
} finally {
document.body.removeChild(container);
}
}
// 图片加载等待函数
const waitForImages = (element: HTMLElement) => {
return new Promise<void>((resolve) => {
const images = element.getElementsByTagName("img");
let loaded = 0;
const checkDone = () => {
if (loaded >= images.length) resolve();
};
if (images.length === 0) return resolve();
Array.from(images).forEach((img) => {
if (img.complete) {
loaded++;
checkDone();
} else {
img.onload = () => {
loaded++;
checkDone();
};
img.onerror = checkDone;
}
});
});
};
export function htmlToPdf(htmlCode: string) {
// 1. 动态创建一个 div 元素,并配置为隐藏(display: none)
const container = document.createElement("div");
container.innerHTML = htmlCode;
container.style.display = "none";
document.body.appendChild(container);
// 2. 为了让 html2canvas 能捕获内容,将 display 修改为 block,并移至视野之外
container.style.display = "block";
container.style.position = "absolute";
container.style.top = "-9999px";
container.style.left = "-9999px";
window.pageYOffset = 0;
document.documentElement.scrollTop = 0;
document.body.scrollTop = 0;
setTimeout(() => {
html2canvas(container, {
allowTaint: true,
useCORS: true,
scale: 2, // 提升画面质量,但是会增加文件大小
height: container.scrollHeight, // 需要注意,element的 高度 宽度一定要在这里定义一下,不然会存在只下载了当前你能看到的页面 避雷避雷!!!
windowHeight: container.scrollHeight,
}).then(function (canvas) {
var contentWidth = canvas.width;
var contentHeight = canvas.height;
// console.log('contentWidth', contentWidth)
// console.log('contentHeight', contentHeight)
// 一页pdf显示html页面生成的canvas高度;
var pageHeight = (contentWidth * 841.89) / 592.28;
// 未生成pdf的html页面高度
var leftHeight = contentHeight;
// console.log('pageHeight', pageHeight)
// console.log('leftHeight', leftHeight)
// 页面偏移
var position = 0;
// a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高 //40是左右页边距
var imgWidth = 595.28 - 40;
var imgHeight = (592.28 / contentWidth) * contentHeight;
var pageData = canvas.toDataURL("image/jpeg", 1.0);
var pdf = new jsPDF("p", "pt", "a4");
// 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
// 当内容未超过pdf一页显示的范围,无需分页
if (leftHeight < pageHeight) {
// console.log('没超过1页')
pdf.addImage(pageData, "JPEG", 20, 20, imgWidth, imgHeight);
} else {
while (leftHeight > 0) {
// console.log('超过1页')
pdf.addImage(pageData, "JPEG", 20, position, imgWidth, imgHeight);
leftHeight -= pageHeight;
position -= 841.89;
// 避免添加空白页
if (leftHeight > 0) {
pdf.addPage();
}
}
}
pdf.save("out.pdf");
});
}, 1000);
}
export async function getPdfData(file: File) {
try {
const arrayBuffer = await file.arrayBuffer();
const text = await pdfToText(new Uint8Array(arrayBuffer));
return text;
} catch (error) {
console.error("Error extracting PDF content:", error);
throw error;
}
}