在前端導出PDF,解決中文亂碼一直是一個頭疼的問題。要解決這個問題,需要將ttf等字體文件內容註冊到頁面PDF生成器中。但是之前網頁是沒有權限直接獲取客户機器字體文件,這時就需要從服務器下載字體文件或者提示用户選擇字體文件上傳到頁面。對於動輒數十兆(M)的中文字體文件,網絡不好時並不是一個好的解決方案。
Chrome 103
Chrome 103版本中新的字體API可以讓web應用獲取到用户在本地電腦上安裝的所有字體信息,同時還可以獲取到字體內容。
調用window.queryLocalFonts(),會返回用户安裝字體的數組。
const pickedFonts = await self.queryLocalFonts();
for (const fontData of pickedFonts) {
console.log(fontData.postscriptName);
console.log(fontData.fullName);
console.log(fontData.family);
console.log(fontData.style);
}
處於安全性的考慮,獲取字體信息需要獲取到用户的授權。當第一調用queryLocalFonts時,Chrome會彈出權限申請:
同意後,就可以獲取到所有安裝字體信息了
使用navigator.permissions.query可以檢查權限
async function requestPremission(){
const { state } = await navigator.permissions.query({
name: "local-fonts"
});
console.log(state)
if (state === 'granted') {
query();
} else if (state === 'prompt') {
alert("請授予權限!")
query();
}
else{
alert("沒有權限獲取字體")
}
}
使用本地字體導出PDF
選擇需要使用的字體內容,註冊到PDF生成工具中
使用blob 方法可以獲取字體文件內容
let currentFont = fontList[fontListSelect.value];
const blob = await currentFont.blob();
使用字體名稱註冊
//將Blob 對象轉換成 ArrayBuffer
var reader = new FileReader();
reader.onload = function (e) {
var fontrrayBuffer = reader.result;
var fonts = GC.Spread.Sheets.PDF.PDFFontsManager.getFont(currentFont.family) || {};
fonts[fontType] = fontrrayBuffer;
GC.Spread.Sheets.PDF.PDFFontsManager.registerFont(currentFont.family, fonts);
}
reader.readAsArrayBuffer(blob);
導出含有本地自定義字體的PDF:
注意:使用本地字體也有風險,如果用户沒有安裝必要的字體,在網頁中瀏覽器會用其他字體渲染但是導出PDF可能還會亂嗎,這時還需要從服務器下載字體或者用其他字體文件代替。