HtmlToPdf/src
2026-03-16 18:10:38 +08:00
..
HtmlToPdfService.Admin init 2025-12-11 23:35:52 +08:00
HtmlToPdfService.Api init 2025-12-11 23:35:52 +08:00
HtmlToPdfService.Client 21 2026-03-16 18:10:38 +08:00
HtmlToPdfService.Core init 2025-12-11 23:35:52 +08:00
HtmlToPdfService.Infrastructure init 2025-12-11 23:35:52 +08:00
HtmlToPdfService.Queue init 2025-12-11 23:35:52 +08:00
HtmlToPdfService.Tests init 2025-12-11 23:35:52 +08:00
docker-compose.dev.yml init 2025-12-11 23:35:52 +08:00
docker-compose.yml init 2025-12-11 23:35:52 +08:00
Dockerfile init 2025-12-11 23:35:52 +08:00
HtmlToPdfService.sln 21 2026-03-16 18:10:38 +08:00
README.md init 2025-12-11 23:35:52 +08:00

HTML to PDF Service v2.0

高性能 HTML/URL 转 PDF/图片 微服务,基于 .NET 9 和 PuppeteerSharp。

功能特性

核心功能

  • HTML/URL 转 PDF
  • HTML/URL 转图片PNG/JPEG/WebP
  • 异步任务队列Redis
  • 同步转换MVP 兼容)
  • 浏览器池管理(自愈、健康检查、内存阈值重启)
  • 批量任务提交
  • 任务回调含重试、HMAC 签名)

安全特性

  • API Key 认证
  • 请求限流IP/用户维度)
  • SSRF 防护
  • 幂等性支持Idempotency-Key

运维特性

  • Prometheus 指标
  • 健康检查ready/live 探针)
  • 管理后台 API
  • Docker 部署
  • 结构化日志Serilog

技术栈

  • .NET 9
  • PuppeteerSharp 20.x
  • Redis任务队列
  • Prometheus监控
  • Docker / Docker Compose

快速开始

Docker Compose 部署

cd src
docker-compose up -d

服务启动后访问:

本地开发

# 启动 Redis
docker run -d --name redis -p 6379:6379 redis:7-alpine

# 进入 src 目录
cd src

# 还原依赖
dotnet restore

# 运行服务
dotnet run --project HtmlToPdfService.Api

API 接口

异步任务接口(推荐)

# 提交 PDF 转换任务
curl -X POST http://localhost:5000/api/tasks/pdf \
  -H "Content-Type: application/json" \
  -d '{
    "source": { "type": "html", "content": "<h1>Hello</h1>" },
    "callback": { "url": "https://your-callback-url.com/webhook" }
  }'

# 提交图片转换任务
curl -X POST http://localhost:5000/api/tasks/image \
  -H "Content-Type: application/json" \
  -d '{
    "source": { "type": "url", "content": "https://www.baidu.com/" },
    "options": { "format": "png", "fullPage": true }
  }'

# 查询任务状态
curl http://localhost:5000/api/tasks/{taskId}

# 下载结果
curl -O http://localhost:5000/api/tasks/{taskId}/download

# 取消任务
curl -X DELETE http://localhost:5000/api/tasks/{taskId}

# 批量提交
curl -X POST http://localhost:5000/api/tasks/batch \
  -H "Content-Type: application/json" \
  -d '{
    "tasks": [
      { "type": "pdf", "source": { "type": "html", "content": "<h1>Doc 1</h1>" } },
      { "type": "pdf", "source": { "type": "html", "content": "<h1>Doc 2</h1>" } }
    ]
  }'

# 预检Dry-run
curl -X POST http://localhost:5000/api/tasks/validate \
  -H "Content-Type: application/json" \
  -d '{
    "source": { "type": "url", "content": "https://example.com" }
  }'

同步接口MVP 兼容)

# HTML 转 PDF同步
curl -X POST http://localhost:5000/api/pdf/convert/html \
  -H "Content-Type: application/json" \
  -d '{"html": "<h1>Hello World</h1>"}' \
  -o document.pdf

# URL 转 PDF同步
curl -X POST http://localhost:5000/api/pdf/convert/url \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com"}' \
  -o document.pdf

# HTML 转图片(同步)
curl -X POST http://localhost:5000/api/image/convert/html \
  -H "Content-Type: application/json" \
  -d '{"html": "<h1>Hello</h1>", "options": {"format": "png"}}' \
  -o screenshot.png

系统接口

# 健康检查
curl http://localhost:5000/health

# 就绪探针
curl http://localhost:5000/health/ready

# 存活探针
curl http://localhost:5000/health/live

# Prometheus 指标
curl http://localhost:5000/metrics

管理接口

# 仪表盘数据
curl http://localhost:5000/api/admin/dashboard

# 任务列表
curl http://localhost:5000/api/admin/tasks

# 处理卡死任务
curl -X POST http://localhost:5000/api/admin/tasks/handle-stalled

# 清理过期任务
curl -X POST "http://localhost:5000/api/admin/tasks/cleanup?retentionDays=7"

# 浏览器池状态
curl http://localhost:5000/api/admin/browser-pool

# 预热浏览器池
curl -X POST http://localhost:5000/api/admin/browser-pool/warmup

配置说明

主要配置项在 appsettings.json 中:

{
  "PdfService": {
    "BrowserPool": {
      "MaxInstances": 10,
      "MinInstances": 2,
      "MaxConcurrent": 5,
      "MaxTasksPerBrowserInstance": 100,
      "BrowserRestartMemoryMb": 600
    },
    "TaskQueue": {
      "Type": "Redis",
      "Redis": { "ConnectionString": "localhost:6379" },
      "WorkerCount": 5
    },
    "Storage": {
      "Type": "Local",
      "LocalPath": "/app/files"
    },
    "Security": {
      "RequireAuthentication": false,
      "BlockPrivateNetworks": true
    },
    "RateLimit": {
      "Enabled": true,
      "RequestsPerMinutePerIp": 60
    }
  }
}

存储配置

支持三种存储类型:Local本地OSS阿里云COS腾讯云

本地存储(默认)

{
  "Storage": {
    "Type": "Local",
    "LocalPath": "/app/files",
    "RetentionHours": 168,
    "AutoCleanup": true
  }
}

阿里云 OSS 存储

{
  "Storage": {
    "Type": "OSS",
    "SaveLocalCopy": false,
    "OSS": {
      "Endpoint": "oss-cn-hangzhou.aliyuncs.com",
      "AccessKeyId": "your-access-key-id",
      "AccessKeySecret": "your-access-key-secret",
      "BucketName": "your-bucket-name",
      "CdnDomain": "",
      "UseHttps": true,
      "PathPrefix": "htmltopdf",
      "UrlExpireSeconds": 3600
    }
  }
}

腾讯云 COS 存储

{
  "Storage": {
    "Type": "COS",
    "SaveLocalCopy": false,
    "COS": {
      "Region": "ap-guangzhou",
      "SecretId": "your-secret-id",
      "SecretKey": "your-secret-key",
      "BucketName": "your-bucket-1250000000",
      "CdnDomain": "",
      "UseHttps": true,
      "PathPrefix": "htmltopdf",
      "UrlExpireSeconds": 3600
    }
  }
}

配置说明:

  • Type: 存储类型,可选 LocalOSSCOS
  • SaveLocalCopy: 使用云存储时是否同时保存本地副本
  • CdnDomain: CDN 加速域名(可选)
  • PathPrefix: 存储路径前缀
  • UrlExpireSeconds: 签名 URL 过期时间0 表示永不过期

项目结构

src/
├── HtmlToPdfService.Api/           # Web API 层
│   ├── Controllers/                # API 控制器
│   ├── Middleware/                 # 中间件
│   └── Program.cs                  # 入口点
├── HtmlToPdfService.Core/          # 核心业务层
│   ├── Services/                   # PDF/图片转换服务
│   ├── Pool/                       # 浏览器池
│   ├── Storage/                    # 文件存储
│   └── Callback/                   # 回调服务
├── HtmlToPdfService.Queue/         # 任务队列层
│   ├── Models/                     # 任务模型
│   └── Workers/                    # 后台 Worker
├── HtmlToPdfService.Infrastructure/# 基础设施层
│   ├── Authentication/             # 认证
│   ├── RateLimit/                  # 限流
│   ├── Security/                   # 安全
│   └── Monitoring/                 # 监控
└── HtmlToPdfService.Tests/         # 测试
    ├── Unit/                       # 单元测试
    └── Integration/                # 集成测试

运行测试

cd src
dotnet test

License

MIT