You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在NextJS API路由中使用Satori:将SVG转为PNG并返回的方法

解决Satori生成SVG转PNG并在Next.js 13 API路由返回的问题

先澄清你对Satori文档的误解

你看到的那段文档内容,是指当你需要在Satori渲染的JSX内容中嵌入PNG图片时,直接传入base64编码的字符串或Buffer作为<img>的src,避免额外的文件IO操作。这和把Satori生成的SVG转为PNG是两回事——Satori本身只负责生成SVG,转PNG需要依赖专门的渲染库。

解决方案步骤

1. 安装必要依赖

使用@resvg/resvg-js来将SVG转为PNG,这是Vercel官方推荐的配套库:

npm install @resvg/resvg-js
# 或
yarn add @resvg/resvg-js

2. 调整API路由代码

注意以下关键细节:

  • Satori的第一个参数应该是JSX元素(不是字符串),需导入React
  • 指定API路由使用Node.js Runtime(@resvg/resvg-js目前不完全支持Edge Runtime)
  • 使用resvg处理SVG字符串生成PNG Buffer
  • 设置正确的响应头,返回PNG文件

完整代码示例:

import { NextResponse } from 'next/server';
import satori from 'satori';
import { Resvg } from '@resvg/resvg-js';
import fs from 'fs/promises';
import React from 'react';

// 指定使用Node.js Runtime,避免resvg的兼容问题
export const runtime = 'nodejs';

export async function GET() {
  const fontUrl = '/Users/anton/projects/new_test/src/app/assets/fonts/NotoSans/NotoSans-Bold.ttf';
  const fontArrayBuf = await fs.readFile(fontUrl);

  // 生成SVG(注意这里是JSX元素,不是字符串)
  const svg = await satori(
    <div style={{ color: 'red', fontSize: 48, fontFamily: 'Noto Sans' }}>hello, world</div>,
    {
      width: 600,
      height: 400,
      fonts: [
        {
          name: 'Noto Sans',
          data: fontArrayBuf,
          weight: 700, // 对应Bold字体的weight是700,之前写400不匹配
          style: 'normal',
        },
      ],
    }
  );

  // 将SVG转为PNG Buffer
  const resvg = new Resvg(svg, {
    fitTo: {
      mode: 'width',
      value: 600,
    },
  });
  const pngBuffer = resvg.render();

  // 返回PNG文件
  return new NextResponse(pngBuffer.asPng(), {
    headers: {
      'Content-Type': 'image/png',
      'Content-Disposition': 'inline; filename="generated-image.png"',
    },
  });
}

3. 解决resvg加载器配置错误

如果之前遇到Next.js的加载器错误,核心原因是Edge Runtime的环境限制。上面的代码中已经添加了export const runtime = 'nodejs',会让该API路由使用Node.js环境,避免兼容问题。

若仍有问题,可检查:

  • 确保@resvg/resvg-js版本为最新
  • 确认未在Edge Runtime环境下使用该库(目前Edge支持仍在完善中)

关键说明

  • 字体weight需与实际字体文件匹配:你使用的是NotoSans-Bold.ttf,对应字重应为700(400是常规字重)
  • Satori必须接收JSX元素,不能直接传HTML字符串,否则样式和渲染会异常
  • 返回PNG时,必须设置Content-Type: image/png,确保浏览器能正确识别图片格式

内容的提问来源于stack exchange,提问作者antonwilhelm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 17:45:55