美文网首页Nestjs前端应用
用 NestJs 做一个会员证书 生成服务

用 NestJs 做一个会员证书 生成服务

作者: 思考蛙 | 来源:发表于2021-07-17 14:34 被阅读0次
    nestjs+sharp

    背景

    项目源码地址在文未

    在一个会员认证系统中收到了一个证书生成需求:

    • 在设计模板中填充中文会员名、会员到期信息(未来需要增加二维码)
    • 可以根据不同的提交参数生成并下载高清会员证书
    • 可按指定字体绘制到图片

    这个需求中主要体现两个要求:在特定的模板中填充中文信息、根据提交的参数返回证书图、需要字体文件处理。需求比较清晰简单,但是实现上面我们还是要设计一下。

    证书示例

    template-image.png

    选型

    应用框架
    近期项目大部分都是基于 nodejs 平台的,并且 nestjs 这个框架我们运用的不错,简洁高效,所以 api 服务就选用了 Nestjs

    图像处理
    因为需求中涉及了图像处理,而在 nodejs 社区中最知名的是 Sharp 这个库。

    这个模块可将常见格式的大图像转换为较小的、web友好的JPEG、PNG、WebP和不同尺寸的AVIF图像。模块的实现基于 libvips,调整图像大小通常比使用最快的ImageMagick和GraphicsMagick设置快4x-5x倍。并且大多数运行Node.js v10+的现代macOS、Windows和Linux系统不需要任何额外的安装或运行时依赖项。

    文字处理
    由于我们需要将文字写入到图片中,比如会员证书中设计是用的这个字体 NotoSerifCJKsc-Bloack.oft,那么就需要根据请求数据填充的内容也是要应用这个字体。这里我们选用了 text-to-svg 这个模块,它的最大特点是可以将字体文件转换为 svg 格式,处理成适量格式后图像中的文字不会失真和乱码。

    程序开发

    环境和工程目录建立

    $ npm i -g @nestjs/cli
    $ nest new nestjs-sharp-server
    

    安装主要依赖

    yarn add sharp text-to-svg
    yarn add types/sharp -D
    

    项目整体结构

    .
    ├── Dockerfile
    ├── README.md
    ├── docker-compose.yml
    ├── fonts     #字体文件
    │   ├── NotoSerifCJKsc-Black.otf
    │   └── NotoSerifCJKsc-SemiBold.otf
    ├── image.png
    ├── nest-cli.json
    ├── package.json
    ├── src
    │   ├── app.controller.spec.ts
    │   ├── app.controller.ts    # API实现
    │   ├── app.module.ts
    │   ├── app.service.ts
    │   ├── info.interface.ts
    │   └── main.ts
    ├── template-image.png    #会员证书模板
    ├── test
    │   ├── app.e2e-spec.ts
    │   └── jest-e2e.json
    ├── tsconfig.build.json
    ├── tsconfig.json
    ├── tslint.json
    ├── yarn-error.log
    └── yarn.lock
    
    

    重点代码

    图像生成函数

        async generateImage(info: InfoInterface): Promise<Buffer> {
            let bgPath = path.join(process.cwd(), '/template-image.png');
            let textToSVG = Text2SVG.loadSync(path.resolve(process.cwd() + '/fonts/', 'NotoSerifCJKsc-SemiBold.otf')); // 加载字体文件
    
            let options = {
                x: 0,         //文本开头的水平位置(默认值:0)
                y: 0,         // 文本的基线的垂直位置(默认值:0)
                fontSize: 32, // 字体大小
                anchor: 'top', // 坐标中的对象锚点
                // letterSpacing: "",  // 设置字母的间距
                attributes: {
                    fill: '#000', // 文字颜色
                },
            };
            const nameSVG = textToSVG.getSVG(info.name + ':', options);
            const dateSVG = textToSVG.getSVG(info.date, options);
            const bufferNameTextSVG = Buffer.from(nameSVG);
            const bufferDateTextSVG = Buffer.from(dateSVG);
            // const qrcode
            return sharp(bgPath)
                .composite([ {
                    // input: this.generateMimeTypeOverlay('image'),
                    input: bufferNameTextSVG,
                    left: 267,
                    top: 725,
                    // gravity: sharp.gravity.center,
                }, {
                    input: bufferDateTextSVG,
                    left: 407,
                    top: 969,
                } ]).toBuffer();
        }
    

    GET API

        @Get()
        getCertificate(@Query() query: any, @Res() res: Response) {
            this.generateImage({
                ...query,
    
            }).then((buffer) => {
    
                const stream = this.getReadableStream(buffer);
    
                res.set({
                    'Cache-Control': 'no-cache',
                    'Content-Type': 'image/png',
                    'Content-Length': buffer.length,
                    'Content-Disposition': 'attachment; filename=certificate.png',
                });
    
                stream.pipe(res);
            });
    
        }
    

    请求示例

    GET http://localhost:3000/?name=名字&date=2021-01-01至2022-01-02
    
    ➜  nestjs-sharp-server git:(main) ✗ yarn start
    yarn run v1.22.10
    warning ../package.json: No license field
    $ nest start
    [Nest] 85553   - 07/17/2021, 2:25:36 PM   [NestFactory] Starting Nest application...
    [Nest] 85553   - 07/17/2021, 2:25:36 PM   [InstanceLoader] AppModule dependencies initialized +14ms
    [Nest] 85553   - 07/17/2021, 2:25:36 PM   [RoutesResolver] AppController {}: +6ms
    [Nest] 85553   - 07/17/2021, 2:25:36 PM   [RouterExplorer] Mapped {, GET} route +2ms
    [Nest] 85553   - 07/17/2021, 2:25:36 PM   [NestApplication] Nest application successfully started +2ms
    
    

    Post man测试

    image.png

    总结

    本篇文章介绍了如何使用 nestjs + sharp 模块,按特定模板生成图片的示例。其中特点是讲解了 Nestjs框架与sharp 与实际应用结合,并给出了一定的解决方案。

    项目源码如下,供参考
    https://github.com/baisheng/nestjs-sharp-server

    相关文章

      网友评论

        本文标题:用 NestJs 做一个会员证书 生成服务

        本文链接:https://www.haomeiwen.com/subject/myqwpltx.html