From f40884d2ba2007c065435dfe9bc603809a69b1a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B4=AE=E7=94=9F?= Date: Sat, 21 Mar 2020 09:42:41 +0800 Subject: [PATCH] =?UTF-8?q?:fire:=20=E6=96=B0=E5=A2=9E=E5=8A=A8=E6=80=81?= =?UTF-8?q?=E7=94=9F=E6=88=90=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 ++- doc_img/api/generate_fonts_dynamically.jpg | Bin 0 -> 32864 bytes src/app.controller.ts | 24 +++++-- src/app.service.ts | 79 ++++++++++++++++++++- 4 files changed, 103 insertions(+), 8 deletions(-) create mode 100644 doc_img/api/generate_fonts_dynamically.jpg diff --git a/README.md b/README.md index 75d4916..57f0cea 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,13 @@ ui 需要展现一些特定的字体,但直接引入字体包又过大,于 ### 动态生成字体 -http://127.0.0.1:3000/generate_fonts_dynamically/font/1584688387272/优设标题黑.ttf +![generate_fonts_dynamically](./doc_img/api/generate_fonts_dynamically.jpg) + +#### 请注意 + +只支持生成 .ttf .eot .woff .svg 这几种格式 + +如果 text 参数为空将会返回整个字体包 ## 写项目时遇到的问题 diff --git a/doc_img/api/generate_fonts_dynamically.jpg b/doc_img/api/generate_fonts_dynamically.jpg new file mode 100644 index 0000000000000000000000000000000000000000..93c38389d6d43c82efbb2aa41f4c93315d2613d2 GIT binary patch literal 32864 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 literal 0 HcmV?d00001 diff --git a/src/app.controller.ts b/src/app.controller.ts index 522b0f6..ce7b86e 100644 --- a/src/app.controller.ts +++ b/src/app.controller.ts @@ -11,6 +11,7 @@ import { AppService } from './app.service'; import { join } from 'path'; import { promises as fs } from 'fs'; import { Request } from 'express'; +import { Stream } from 'stream'; @Controller() export class AppController { constructor(private readonly appService: AppService) {} @@ -30,13 +31,28 @@ export class AppController { /** 压缩字体 */ @Get('generate_fonts_dynamically*') - generate_fonts_dynamically( - @Req() req:Request, + async generate_fonts_dynamically( + @Req() req: Request, + @Res() res, @Query('text') text: string, @Query('font') font: string, @Query('temp') temp: string, ) { - const format=req.url.match(/\.(.*)\?/)[1] - return this.appService.generate_fonts_dynamically(text, font,temp,format); + console.time() + const type = req.url.match(/\.(.*)\?/)[1]; + const file = await this.appService.generate_fonts_dynamically( + text, + font, + temp, + type, + ); + res.set({ + 'Content-Type': `font/${type}`, + }); + const bufferStream = new Stream.PassThrough(); + bufferStream.end(file); + bufferStream.pipe(res); + console.timeEnd() + } } diff --git a/src/app.service.ts b/src/app.service.ts index ca4f78f..03c132b 100644 --- a/src/app.service.ts +++ b/src/app.service.ts @@ -2,7 +2,9 @@ import { Injectable } from '@nestjs/common'; import Fontmin from 'fontmin'; const { zip } = require('zip-a-folder'); import { join } from 'path'; +import crypto from 'crypto'; import { config } from './config'; +import { promises as fs } from 'fs'; @Injectable() export class AppService { font_min(text: string, font: string) { @@ -47,12 +49,83 @@ export class AppService { }); } - generate_fonts_dynamically( + async generate_fonts_dynamically( text: string, font: string, temp: string, - format: string, + type: string, ) { - return 11; + const hash = crypto.createHash('md5'); + hash.update(`${type}${font}${text}`); + const hash_str = hash.digest('hex'); + const srcPath = `./src/font/${font}.ttf`; // 字体源文件 + const outPath = `asset/dynamically/${hash_str}`; + const destPath = `./${outPath}`; // 输出路径 + + const full_path = join(__dirname, '../../', destPath, `${font}.${type}`); + /** 需要持久化 */ + if (temp !== 'true') { + try { + return await fs.readFile(full_path); + } catch (error) { + console.log(`开始生成 ${full_path}`,error); + } + } + // 初始化 + const fontmin = new Fontmin() + .src(srcPath) // 输入配置 + .use( + Fontmin.glyph({ + text, // 所需文字 + }), + ); + + if ('eot' === type) { + fontmin.use(Fontmin.ttf2eot()); // eot 转换插件 + } + if ('woff' === type) { + fontmin.use(Fontmin.ttf2woff()); // eot 转换插件 + } + if ('svg' === type) { + fontmin.use(Fontmin.ttf2svg()); // eot 转换插件 + } + /** 缓存数据 */ + if (temp !== 'true') { + fontmin.dest(destPath) + } + + + // 执行 + return new Promise((resolve, reject) => { + fontmin.run(async function(err, files, stream) { + if (err) { + // 异常捕捉 + reject(err); + } else { + const buffer = files.filter(f => + /** 筛选需要的类型 */ + (f.history[f.history.length - 1] as string).endsWith(type), + )[0]._contents; + resolve(buffer); // 成功 + /** 存个日志 */ + if (temp !== 'true') { + const content_path = join( + __dirname, + '../../', + destPath, + `content.txt`, + ); + try { + await fs.appendFile( + content_path, + `type:${type}\nfont:${font}\ntext:${text}`, + ); + } catch (error) { + console.error(`写 ${content_path} 失败`); + } + } + } + }); + }); } }