通过 nodejs 下载 google 字体,实时转换为 base64 以便在 css datauri 中使用

Downloading google font via nodejs, live convert to base64 for use in css datauri

最终目标是生成并提供一个 svg,它将所有外部元素内联为 datauris,以便生成的 svg 可以在 html5 canvas 中使用以动态生成图像。

我已经设法在输出 svg 的服务器上动态下载和嵌入图像,但 svg 还包括 google 用户可以随机 select 的字体,所以还需要从google下载指定的字体文件,将其转换为base64,并将其作为@font-face中的datauri放入svg的css。

到目前为止字体只是拒绝工作。

如果我使用在线服务来转换完全相同的字体文件并将其粘贴到我转换后的字体 datauri 的位置,它就可以工作,所以我下载字体的方式或我的方式有问题m 将其转换为 base64。

所有下载和转换都在服务器上进行,因此我可以为 'all-in-one' svg 提供服务器。我正在使用 Firebase 的 Cloud Functions,它使用 nodejs。

我知道了,所以我可以下载 google 字体导入文件(例如:https://fonts.googleapis.com/css?family=Comfortaa),其中 return 是 css @font-face 导入字符串,例如:

@font-face {
  font-family: 'Comfortaa';
  font-style: normal;
  font-weight: 400;
  src: local('Comfortaa Regular'), local('Comfortaa-Regular'), url(https://fonts.gstatic.com/s/comfortaa/v12/1Ptsg8LJRfWJmhDAuUs4QIFqL_KWxWMT.woff2) format('woff2');
}

然后我提取实际字体文件的 url(即:https://fonts.gstatic.com/s/comfortaa/v12/1Ptsg8LJRfWJmhDAuUs4QIFqL_KWxWMT.woff2)并使用 nodejs 的 https 下载字体和 return 作为承诺。

function getFontToImport( file ) {
    return new Promise( ( resolve , reject ) => {
        https.get( file , ( res ) => {
            const { statusCode } = res;
            const contentType = res.headers['content-type'];
            let error;
            if (statusCode !== 200) {
                error = new Error('Request Failed.\n' + `Status Code: ${statusCode}`);
            }
            if ( error ) {
                // consume response data to free up memory
                res.resume();
                resolve( error ) ;
            }

            //res.setEncoding('utf8');
            let rawData = '';
            res.on('data', (chunk) => { rawData += chunk; });
            res.on('end', () => {
                try {
                    resolve( rawData ) ;
                } catch ( e ) {
                  console.log( 'Could not log the file' ) ;
                  console.error(e.message);
                  resolve( e.message ) ;
                }
            });
        }).on( 'error' , (e) => {
          console.error( 'Got error:' + e.message ) ;
          resolve( e.message ) ;    
        });    
    }) ;    
}

我随后将该数据转换为 base64,使用:

const base_64 = new Buffer( rawData ).toString( 'base64' ) ;

我将其注入到我创建的@font-face css 中的 svg 代码中,但字体无法显示。如果我使用在线转换器将相同的字体转换为 base64,并将其粘贴到 @font-face 中代替我的 base64 datauri,文本会正确显示,所以问题与我的下载方式有关 and/or 转换字体。

当我将通过我的 nodejs 函数下载的字体版本与通过我的浏览器下载的相同文件进行比较时,它们看起来确实大不相同。

这是一个 link 页面,使用了我正在处理的一些不同输出的函数:https://us-central1-project-7161459789373699890.cloudfunctions.net/font64?font=Comfortaa

我认为问题出在我下载字体的方式上。我真的不知道节点,所以我只是复制了一个例子,它对图像很有效。它对字体不起作用,所以我按照建议取出了编码,但仍然没有运气。

如果有人可以就通过节点加载的字体数据与使用浏览器直接访问字体 link 下载的字体数据之间的区别提出任何建议或澄清,我会非常感谢。

必须将编码设置为 'binary'。

默认情况下它设置为 utf8,因此删除编码设置误导我认为数据将以其默认编码传递。将编码设置为二进制允许数据以正确的格式通过,然后允许它正确地转换为 base64,这允许它在用作 datauri 时正确显示。