代码之家  ›  专栏  ›  技术社区  ›  Andrew Reid

通过nodejs下载google字体,实时转换为base64以用于css datauri

  •  0
  • Andrew Reid  · 技术社区  · 6 年前

    最终目标是生成并提供一个svg,该svg将所有外部元素作为DataURI内联,以便生成的svg可以在html5画布中用于动态生成图像。

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

    到目前为止,这些字体都不起作用。

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

    所有的下载和转换都是在服务器上进行的,因此我可以为“一体式”svg提供服务器。我正在使用Firebase的云函数,它使用nodejs。

    我有它,所以我可以下载谷歌字体导入文件(例如: https://fonts.googleapis.com/css?family=Comfortaa ),它返回一个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下载字体并作为承诺返回。

    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\u 64=新缓冲区(rawData)。toString('base64');

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

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

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

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

    如果有人能就通过节点加载的字体数据与通过浏览器直接访问字体链接下载的字体数据之间的差异给出任何建议或澄清,我将不胜感激。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Andrew Reid    6 年前

    必须将编码设置为“二进制”。

    默认情况下,它被设置为utf8,因此删除编码设置会误导我,使我误以为数据将以其默认编码进行传输。将编码设置为二进制可以使数据以正确的格式传输,然后可以将其正确转换为base64,从而在用作datauri时可以正确显示。