版本:适用于 MiniPdf 0.16.0 及以上版本
许可协议:Apache 2.0,开源可免费商用
官方仓库:https://github.com/mini-software/MiniPdf
目录
- 概述
- 环境要求
- 安装方式
- 快速开始
- API 参考
- 进阶使用
- 命令行工具(MiniPdf.Cli)
- 在 Web 项目中集成
- 容器/Docker 环境集成
- 功能支持说明与局限性
- 性能与基准测试
- 常见问题 FAQ
- 相关资源
1. 概述
1.1 什么是 MiniPdf
MiniPdf 是由 mini-software 团队(MiniExcel、MiniWord 同作者)开发的一个极简、零外部依赖的 .NET 库,专为将 Office 文件(Excel .xlsx、Word .docx)转换为 PDF 而设计。
它完全基于 .NET 内置 API 实现,无需安装 Microsoft Office、LibreOffice、Adobe Acrobat 或任何第三方软件,是目前全球首个开源可商用的 .NET Office 转 PDF 工具。
1.2 核心优势
| 优势 | 说明 |
|---|---|
| 零依赖 | 不依赖 COM、Office、LibreOffice、Docker |
| 轻量化 | 仅使用 .NET 内置 API,包体积小 |
| 免费商用 | Apache 2.0 协议,企业项目可直接使用 |
| 跨平台 | 支持 Windows / Linux / macOS |
| Serverless 就绪 | 适合云函数、容器化部署 |
| 标准输出 | 生成符合 PDF 1.4 标准的文件 |
| Native AOT | 支持编译为零依赖的原生可执行文件 |
1.3 内部技术架构
MiniPdf.ConvertToPdf(公共 API 入口)
│
├─→ ExcelToPdfConverter(Excel 解析 + 布局引擎)
│ │
│ └─→ ExcelReader(解析 .xlsx Open XML)
│
├─→ WordToPdfConverter(Word 解析 + 布局引擎)
│
└─→ PdfWriter(PDF 1.4 文档生成器)
2. 环境要求
2.1 支持的 .NET 框架版本
| 框架 | 最低版本 |
|---|---|
| .NET Framework | 4.6.2 |
| .NET Standard | 2.0 |
| .NET Core / .NET | 6.0、8.0、9.0 |
2.2 依赖说明
| 目标框架 | 所需依赖 |
|---|---|
| .NET Framework 4.6.2 | System.Memory ≥ 4.5.5、System.ValueTuple ≥ 4.5.0 |
| .NET Standard 2.0 | System.Drawing.Common ≥ 8.0.0、System.Memory ≥ 4.5.5 |
| .NET 6.0 / 8.0 / 9.0 | System.Drawing.Common ≥ 8.0.0 |
以上依赖均由 NuGet 自动管理,无需手动安装。
3. 安装方式
3.1 .NET CLI(推荐)
dotnet add package MiniPdf
安装指定版本:
dotnet add package MiniPdf --version 0.16.0
3.2 Visual Studio Package Manager Console
Install-Package MiniPdf
安装指定版本:
Install-Package MiniPdf -Version 0.16.0
3.3 项目文件(.csproj)直接引用
在 .csproj 文件的 <ItemGroup> 中添加:
<ItemGroup>
<PackageReference Include="MiniPdf" Version="0.16.0" />
</ItemGroup>
3.4 Paket CLI
paket add MiniPdf --version 0.16.0
3.5 F# Interactive / Polyglot Notebooks
#r "nuget: MiniPdf, 0.16.0"
4. 快速开始
4.1 引入命名空间
所有功能均通过 MiniSoftware 命名空间下的 MiniPdf 静态类提供:
using MiniSoftware;
4.2 基础示例:Excel 转 PDF
using MiniSoftware;
// 将 Excel 文件转换为 PDF 文件
MiniPdf.ConvertToPdf("data.xlsx", "output.pdf");
Console.WriteLine("转换完成!");
4.3 基础示例:Word 转 PDF
using MiniSoftware;
// 将 Word 文件转换为 PDF 文件
MiniPdf.ConvertToPdf("report.docx", "output.pdf");
Console.WriteLine("转换完成!");
4.4 返回字节数组(不写入文件)
using MiniSoftware;
// 转换后返回 PDF 的字节数组,不直接写入磁盘
byte[] pdfBytes = MiniPdf.ConvertToPdf("data.xlsx");
// 可将 pdfBytes 保存到数据库、返回给前端或做进一步处理
File.WriteAllBytes("output.pdf", pdfBytes);
4.5 从文件流转换
using MiniSoftware;
// 从文件流读取 Excel,返回 PDF 字节数组
using var inputStream = File.OpenRead("data.xlsx");
byte[] pdfBytes = MiniPdf.ConvertToPdf(inputStream);
5. API 参考
5.1 静态方法总览
MiniPdf 类提供以下静态方法(均位于 MiniSoftware 命名空间):
| 方法签名 | 说明 |
|---|---|
ConvertToPdf(string inputPath, string outputPath) |
文件路径 → 文件路径(推荐) |
ConvertToPdf(string inputPath) : byte[] |
文件路径 → 字节数组 |
ConvertToPdf(Stream inputStream) : byte[] |
输入流 → 字节数组 |
ConvertToPdf(Stream inputStream, Stream outputStream) |
输入流 → 输出流 |
RegisterFont(string fontName, byte[] fontBytes) |
注册自定义字体 |
5.2 方法详细说明
ConvertToPdf(string inputPath, string outputPath)
/// <summary>
/// 将 Excel 或 Word 文件转换为 PDF,直接写入目标路径
/// </summary>
/// <param name="inputPath">输入文件路径,支持 .xlsx / .docx</param>
/// <param name="outputPath">输出 PDF 文件路径</param>
public static void ConvertToPdf(string inputPath, string outputPath);
示例:
MiniPdf.ConvertToPdf(@"C:\Documents\report.xlsx", @"C:\Output\report.pdf");
ConvertToPdf(string inputPath) : byte[]
/// <summary>
/// 将 Excel 或 Word 文件转换为 PDF,返回字节数组
/// </summary>
/// <param name="inputPath">输入文件路径,支持 .xlsx / .docx</param>
/// <returns>PDF 文件的字节数组</returns>
public static byte[] ConvertToPdf(string inputPath);
示例:
byte[] pdfData = MiniPdf.ConvertToPdf("invoice.xlsx");
ConvertToPdf(Stream inputStream) : byte[]
/// <summary>
/// 从输入流读取 Office 文件,转换为 PDF 字节数组
/// </summary>
/// <param name="inputStream">输入流(.xlsx 或 .docx 格式)</param>
/// <returns>PDF 文件的字节数组</returns>
public static byte[] ConvertToPdf(Stream inputStream);
示例:
using var stream = File.OpenRead("report.xlsx");
byte[] pdfBytes = MiniPdf.ConvertToPdf(stream);
RegisterFont(string fontName, byte[] fontBytes)
/// <summary>
/// 注册自定义字体,用于替换系统字体(适合无字体环境)
/// 建议在应用程序启动时调用,仅需注册一次
/// </summary>
/// <param name="fontName">字体名称(自定义标识符)</param>
/// <param name="fontBytes">字体文件的字节数组(支持 .ttf / .ttc)</param>
public static void RegisterFont(string fontName, byte[] fontBytes);
示例:
// 程序启动时注册字体(Program.cs 或 Startup.cs)
MiniPdf.RegisterFont("NotoSansSC", File.ReadAllBytes("Fonts/NotoSansSC-Regular.ttf"));
MiniPdf.RegisterFont("NotoColorEmoji", File.ReadAllBytes("Fonts/NotoColorEmoji.ttf"));
6. 进阶使用
6.1 自定义字体(解决中文乱码/字体缺失)
在 Docker 容器、Blazor WASM、Serverless 等无字体环境中,系统可能缺少中文字体,导致生成的 PDF 出现方框或乱码。
解决方案:在程序启动时注册自定义字体。
步骤一:下载中文字体
推荐使用 Noto Sans SC(思源黑体),开源免费可商用。
步骤二:将字体文件放入项目
MyProject/
├── Fonts/
│ └── NotoSansSC-Regular.ttf
├── Program.cs
确保字体文件被复制到输出目录(.csproj):
<ItemGroup>
<None Update="Fonts\NotoSansSC-Regular.ttf">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
步骤三:注册字体
// Program.cs(仅需在应用启动时执行一次)
MiniPdf.RegisterFont("NotoSansSC", File.ReadAllBytes("Fonts/NotoSansSC-Regular.ttf"));
步骤四:正常调用转换
// 注册字体后,正常调用即可,字体会自动匹配
MiniPdf.ConvertToPdf("report.xlsx", "report.pdf");
6.2 多字体注册示例
// 支持多种字体,按名称注册
MiniPdf.RegisterFont("SimSun", File.ReadAllBytes("Fonts/simsun.ttf")); // 宋体
MiniPdf.RegisterFont("SimHei", File.ReadAllBytes("Fonts/simhei.ttf")); // 黑体
MiniPdf.RegisterFont("NotoEmoji", File.ReadAllBytes("Fonts/NotoColorEmoji.ttf")); // Emoji
6.3 异常处理
建议对转换逻辑进行异常捕获:
using MiniSoftware;
try
{
MiniPdf.ConvertToPdf("input.xlsx", "output.pdf");
Console.WriteLine("转换成功");
}
catch (FileNotFoundException ex)
{
Console.WriteLine($"文件未找到:{ex.Message}");
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine($"文件访问权限不足:{ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"转换失败:{ex.Message}");
}
6.4 批量转换
7. 命令行工具(MiniPdf.Cli)
7.1 安装 CLI 工具
dotnet tool install --global MiniPdf.Cli
验证安装:
minipdf --version
7.2 基本命令
# 将 Excel 转为 PDF(输出到同目录,同名 .pdf 文件)
minipdf data.xlsx
# 将 Word 转为 PDF
minipdf report.docx
# 指定输出路径
minipdf report.docx -o /path/to/output.pdf
minipdf data.xlsx --output ./result/output.pdf
# 指定字体目录(批量注册目录下所有字体)
minipdf report.docx --fonts ./Fonts
# 查看帮助
minipdf --help
7.3 使用 Native AOT 独立二进制(无需 .NET 运行时)
适用于服务器无 .NET 运行时环境,下载编译好的原生可执行文件:
下载地址:GitHub Releases
Windows 使用:
# 解压后直接运行
.\minipdf.exe report.docx -o report.pdf
.\minipdf.exe data.xlsx --fonts .\Fonts -o output.pdf
Linux 使用:
# 解压
tar -xzf minipdf-linux-x64.tar.gz
# 赋权
chmod +x minipdf
# 执行转换
./minipdf report.docx -o report.pdf
./minipdf data.xlsx --fonts ./Fonts
macOS 使用:
tar -xzf minipdf-osx-x64.tar.gz
chmod +x minipdf
./minipdf data.xlsx -o output.pdf
8. 在 Web 项目中集成
8.1 ASP.NET Core Web API 示例
在 HTTP 接口中接收文件,转换后直接返回 PDF 流:
using Microsoft.AspNetCore.Mvc;
using MiniSoftware;
[ApiController]
[Route("api/[controller]")]
public class PdfController : ControllerBase
{
/// <summary>
/// 上传 Excel/Word 文件,返回转换后的 PDF
/// </summary>
[HttpPost("convert")]
public IActionResult ConvertToPdf(IFormFile file)
{
if (file == null || file.Length == 0)
return BadRequest("请上传文件");
var ext = Path.GetExtension(file.FileName).ToLower();
if (ext != ".xlsx" && ext != ".docx")
return BadRequest("仅支持 .xlsx 和 .docx 格式");
try
{
using var inputStream = file.OpenReadStream();
byte[] pdfBytes = MiniPdf.ConvertToPdf(inputStream);
return File(pdfBytes, "application/pdf",
Path.GetFileNameWithoutExtension(file.FileName) + ".pdf");
}
catch (Exception ex)
{
return StatusCode(500, $"转换失败:{ex.Message}");
}
}
}
8.2 ASP.NET Core Minimal API 示例
using MiniSoftware;
var builder = WebApplication.CreateBuilder(args);
// 注册字体(适合容器环境)
MiniPdf.RegisterFont("NotoSansSC",
File.ReadAllBytes("Fonts/NotoSansSC-Regular.ttf"));
var app = builder.Build();
app.MapPost("/convert", async (IFormFile file) =>
{
using var stream = file.OpenReadStream();
var pdfBytes = MiniPdf.ConvertToPdf(stream);
return Results.File(pdfBytes, "application/pdf",
Path.ChangeExtension(file.FileName, ".pdf"));
});
app.Run();
8.3 下载 PDF 到浏览器(内联/附件)
// 在浏览器中直接预览 PDF(内联)
Response.Headers["Content-Disposition"] = "inline; filename=output.pdf";
Response.ContentType = "application/pdf";
await Response.Body.WriteAsync(pdfBytes);
// 或作为附件下载
return File(pdfBytes, "application/pdf", "output.pdf");
9. 容器/Docker 环境集成
9.1 Dockerfile 示例
由于 MiniPdf 无需 LibreOffice / Office,Dockerfile 极为简洁:
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
# 安装中文字体支持(可选,或使用 RegisterFont 代替)
RUN apt-get update && apt-get install -y fonts-noto-cjk && rm -rf /var/lib/apt/lists/*
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["MyApp.csproj", "."]
RUN dotnet restore
COPY . .
RUN dotnet build -c Release -o /app/build
FROM build AS publish
RUN dotnet publish -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
# 复制自定义字体(推荐方式)
COPY Fonts/ ./Fonts/
ENTRYPOINT ["dotnet", "MyApp.dll"]
9.2 使用内嵌字体(推荐生产环境)
不依赖系统字体,将字体文件打包进项目:
// Program.cs
var fontPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Fonts");
if (Directory.Exists(fontPath))
{
foreach (var fontFile in Directory.GetFiles(fontPath, "*.ttf"))
{
var fontName = Path.GetFileNameWithoutExtension(fontFile);
MiniPdf.RegisterFont(fontName, File.ReadAllBytes(fontFile));
}
}
10. 功能支持说明与局限性
10.1 Excel (.xlsx) 功能支持矩阵
| 功能 | 支持状态 | 备注 |
|---|---|---|
| 基础文本内容 | ✅ 完全支持 | |
| 字体(名称、大小、粗体、斜体) | ✅ 完全支持 | |
| 单元格背景色 / 字体颜色 | ✅ 完全支持 | |
| 文本对齐(水平 / 垂直) | ✅ 完全支持 | |
| 合并单元格 | ✅ 完全支持 | |
| 边框样式 | ✅ 完全支持 | |
| 嵌入图片(JPEG / PNG) | ✅ 完全支持 | |
| 数字格式化 | ✅ 完全支持 | |
| 多工作表 | ✅ 支持 | 每个 Sheet 对应 PDF 中的独立页 |
| 图表(Charts) | ⚠️ 部分支持 | 渲染为简化矢量近似,复杂图表保真度较低 |
| 长文本自动换行 | ❌ 已知缺陷 | 超出列宽的文本会被截断,待修复 |
| CJK 字符(中日韩) | ⚠️ 部分支持 | 可通过 RegisterFont 解决间距问题 |
| 数据透视表 | ❌ 不支持 | |
| VBA 宏 | ❌ 不支持 |
10.2 Word (.docx) 功能支持矩阵
| 功能 | 支持状态 | 备注 |
|---|---|---|
| 基础段落文本 | ✅ 完全支持 | |
| 字体样式(粗体、斜体、下划线) | ✅ 完全支持 | |
| 标题与列表 | ✅ 完全支持 | |
| 表格 | ✅ 支持 | |
| 嵌入图片 | ✅ 支持 | |
| 复杂排版(多栏、文本框) | ⚠️ 有限支持 | |
| 页眉 / 页脚 | ⚠️ 部分支持 | |
| 目录(TOC) | ❌ 不支持 | |
| 修订记录 | ❌ 不支持 |
10.3 使用建议
- 对于简单表格和文档:MiniPdf 效果优秀,推荐直接使用。
- 对于复杂图表:建议预先评估转换效果,必要时考虑预处理或替代方案。
- 对于中文内容:建议在 Linux/Docker 环境中使用
RegisterFont注册 Noto Sans CJK 字体。 - 对于超长文本单元格:当前版本存在截断问题,可在生成 Excel 时预先设置自动换行或适当的列宽。
11. 性能与基准测试
11.1 官方测试结果
经过 373 个测试用例(与 MiniExcel / Office 365 输出对比)的评估:
| 文档类型 | 用例数 | 🟢 优秀(≥90%) | 🟡 可接受(70%~90%) | 🔴 待改进(<70%) | 平均分 |
|---|---|---|---|---|---|
| XLSX 转 PDF | 191 | 175 | 16 | 0 | 96.9% |
| DOCX 转 PDF | 180 | 178 | 2 | 0 | 97.6% |
| Issue 文件 | 2 | 1 | 1 | 0 | 83.8% |
| 合计 | 373 | 354 | 19 | 0 | 97.2% |
评分维度:文本相似度 40% + 视觉相似度 40% + 页数 20%
11.2 性能特点
- 转换速度快,无需启动外部进程
- 内存占用小,适合高并发场景
- 不产生临时文件(使用内存流时)
12. 常见问题 FAQ
Q1:生成的 PDF 中文显示为方块或乱码?
原因:当前运行环境(容器、Linux)缺少中文字体。
解决方案:
// 程序启动时注册中文字体
MiniPdf.RegisterFont("NotoSansSC",
File.ReadAllBytes("Fonts/NotoSansSC-Regular.ttf"));
或在 Dockerfile 中安装系统字体:
RUN apt-get update && apt-get install -y fonts-noto-cjk
Q2:Excel 中的图表没有正确显示?
原因:MiniPdf 对复杂图表的渲染支持有限,当前版本将图表渲染为简化矢量近似图。
建议:
- 对于必须精确还原图表的场景,可考虑将图表另存为图片后插入 Excel,再进行转换。
- 关注 GitHub Issues 获取后续版本的图表支持进展。
Q3:单元格长文本被截断怎么办?
原因:已知缺陷,超出列宽的文本会被截断而非自动换行。
临时解决方案:在生成 Excel 时,预先设置单元格的自动换行属性,并适当增大列宽。
Q4:如何在 ASP.NET Core 中注册字体(不重复注册)?
// Program.cs - 使用单次初始化
var fontsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Fonts");
if (Directory.Exists(fontsPath))
{
foreach (var ttf in Directory.GetFiles(fontsPath, "*.ttf"))
{
MiniPdf.RegisterFont(Path.GetFileNameWithoutExtension(ttf),
File.ReadAllBytes(ttf));
}
}
Q5:支持异步转换吗?
当前 ConvertToPdf 方法为同步方法。在 Web 场景中,可使用 Task.Run 包装为异步:
byte[] pdfBytes = await Task.Run(() => MiniPdf.ConvertToPdf(inputStream));
Q6:是否支持加密/密码保护的 PDF?
当前版本不支持生成加密 PDF。如需此功能,可在 MiniPdf 转换后使用其他库(如 iTextSharp)对 PDF 进行加密处理。
Q7:与其他 PDF 库相比有哪些不同?
| 特性 | MiniPdf | iTextSharp | Aspose.PDF | LibreOffice |
|---|---|---|---|---|
| 开源免费商用 | ✅ | ⚠️ AGPL | ❌ 商业授权 | ✅ |
| 零依赖 | ✅ | ✅ | ✅ | ❌ 需安装 |
| Office 直接转换 | ✅ | ❌ | ✅ | ✅ |
| 中文支持 | ⚠️ 需字体 | ✅ | ✅ | ✅ |
| 复杂排版保真度 | ⚠️ 一般 | – | ✅ 高 | ✅ 高 |
13. 相关资源
| 资源 | 链接 |
|---|---|
| GitHub 仓库 | https://github.com/mini-software/MiniPdf |
| Gitee 镜像 | https://gitee.com/dotnetchina/MiniPdf |
| NuGet 包 | https://www.nuget.org/packages/MiniPdf/ |
| 在线演示 | https://mini-software.github.io/MiniPdf/ |
| 官方博客介绍 | https://www.cnblogs.com/ITWeiHan/p/19786846 |
| 技术文档(DeepWiki) | https://deepwiki.com/mini-software/MiniPdf |
| GitHub Releases(CLI 二进制) | https://github.com/shps951023/MiniPdf/releases |
| Discord 社区 | https://discord.gg/BUGRRthp |
| QQ 交流群 | 813100564 / 579033769 / 625362917 / 907750429 |
版本历史
| 版本 | 发布日期 | 主要更新 |
|---|---|---|
| 0.16.0 | 2026-03-17 | 当前最新版,支持 .docx 转 PDF,Native AOT 支持 |
📌 提示:MiniPdf 目前处于 Beta 状态,功能仍在持续完善中。如遇到问题,欢迎在 GitHub Issues 提交反馈,或加入社区群交流。
