如何在Firefox中获取@font-face导入字体的Base64数据URI?
获取@font-face加载字体的Base64数据
需求背景
我需要通过JavaScript获取由CSS @font-face 规则加载的字体文件的Base64字符串,以下是测试过程及遇到的问题:
测试代码
<!DOCTYPE html> <html> <head> <title>test</title> <style> @font-face { font-family: 'Impact'; src: url('https://db.onlinewebfonts.com/t/4cbf858ccd9ffd3923bed6843a474080.ttf') format('woff'); font-weight: bold; font-style: normal; } .testfont { font-family: 'Impact', sans-serif; font-weight: bold; } </style> </head> <body> <div class="testfont">Testing the font</div> </body> <script> for(let idss=0; idss<document.styleSheets.length; idss++) { let dss = document.styleSheets[idss]; for(let idcss=0; idcss<dss.cssRules.length; idcss++) { let cssrule = dss.cssRules[idcss]; let csstypename = cssrule.constructor.name; // 替代已废弃的.type属性 if (csstypename == "CSSFontFaceRule") { console.log("idss", idss, "idcss", idcss, "src", cssrule.style.getPropertyValue("src") ); } } } console.log("fonts.size", document.fonts.size ); console.log("fonts.keys", document.fonts.keys()); console.log("fonts.values", document.fonts.values()); console.log("fonts.keys().next().value.family", document.fonts.keys().next().value.family); // .value是FontFace对象 console.log("fonts.check Impact", document.fonts.check('bold 12px Impact')); console.log("fonts.check whatever", document.fonts.check('bold 12px Whatever')); </script> </html>
Firefox下的控制台输出
idss 0 idcss 0 src url("https://db.onlinewebfonts.com/t/4cbf858ccd9ffd3923bed6843a474080.ttf") format("woff") test.html:30:15 fonts.size 1 test.html:35:9 fonts.keys FontFaceSetIterator { } test.html:36:9 fonts.values FontFaceSetIterator { } test.html:37:9 fonts.keys().next().value "Impact" test.html:37:9 fonts.check Impact false test.html:38:9 fonts.check whatever true test.html:39:9
当前遇到的问题
- 能获取
@font-face的CSS声明,也能通过document.fonts.keys().next().value拿到FontFace对象,但对象中没有实际的字体文件数据。 - 尝试用
for(let key of document.fonts.keys()) {console.log("key", key)}遍历document.fonts.keys()时,报错TypeError: document.fonts.keys() is not iterable,不清楚正确的遍历方式。
Firefox中FontFaceSet.check()的特殊行为
不存在的字体
如果我们指定的字体不在FontFaceSet中且不是系统字体,check()会返回true,因为这种情况下我们不会依赖该集合中的任何字体:...
注意:在这种情况下Chrome会错误地返回false,这会使指纹识别更容易,因为攻击者可以轻松测试浏览器拥有哪些系统字体。
由于测试用字体加载速度慢,初始时document.fonts.check('bold 12px Impact')返回false,等字体加载完成后会返回true,此时无法区分已加载字体和不存在的字体。
核心疑问
如果检测到初始时document.fonts.check('bold 12px Impact')为false,等待其变为true后,能否从document.fonts中获取到字体文件的内容(至少在新版Firefox和Chrome中)?
如果此方法不可行,我可能会放弃@font-face,改用JavaScript直接加载字体文件,但更希望保留@font-face写法,再通过JS从浏览器存储中读取字体数据。
内容的提问来源于stack exchange,提问作者sdbbs
相关产品推荐
相关产品推荐

