在日常开发中,我们经常需要处理PDF文档与图片格式之间的转换需求。最近接手的一个企业文档管理系统项目,就涉及到将用户上传的PDF合同转换为图片预览,并进一步转成Base64编码以便前端直接展示的场景。这种技术组合在实际业务中非常实用:
经过实际测试对比,最终选择PdfiumViewer+Ghostscript组合方案:
| 方案 | 优点 | 缺点 |
|---|---|---|
| iTextSharp | 纯C#实现 | 商业授权费用高 |
| PDFium | 渲染质量好,免费 | 需要处理Native DLL依赖 |
| Ghostscript | 支持复杂PDF | 需要单独安装运行时 |
| Aspose.PDF | 功能全面 | 价格昂贵($999/开发者) |
提示:PdfiumViewer本质是PDFium的.NET封装,实测在Win/Linux下都能稳定运行
图片转Base64时需要注意:
using语句csharp复制// 安装NuGet包:PdfiumViewer
public List<Image> ConvertPdfToImages(string pdfPath, int dpi = 300)
{
var images = new List<Image>();
using (var document = PdfDocument.Load(pdfPath))
{
for (int i = 0; i < document.PageCount; i++)
{
using (var image = document.Render(
i,
(int)(document.PageSizes[i].Width * dpi / 72),
(int)(document.PageSizes[i].Height * dpi / 72),
dpi, dpi, false))
{
images.Add(new Bitmap(image));
}
}
}
return images;
}
关键参数说明:
csharp复制public string ImageToBase64(Image image, ImageFormat format)
{
using (var ms = new MemoryStream())
{
image.Save(ms, format);
return Convert.ToBase64String(ms.ToArray());
}
}
// 带DataURI前缀的版本
public string ImageToBase64DataUri(Image image, ImageFormat format)
{
string mimeType = format == ImageFormat.Jpeg ? "jpeg" : "png";
return $"data:image/{mimeType};base64,{ImageToBase64(image, format)}";
}
当处理超过50页的PDF时:
优化后的处理流程:
csharp复制public async Task ProcessLargePdfAsync(string pdfPath, Action<int> progressCallback)
{
await Task.Run(() => {
using (var doc = PdfDocument.Load(pdfPath))
{
for (int i = 0; i < doc.PageCount; i++)
{
// 处理当前页
progressCallback?.Invoke(i * 100 / doc.PageCount);
// 每5页释放一次内存
if (i % 5 == 0) GC.Collect();
}
}
});
}
推荐三级缓存:
症状:中文显示为方框
解决方案:
bash复制# Linux下安装中文字体
sudo apt install fonts-wqy-zenhei
典型场景:
诊断工具:
GC.GetTotalMemory()监控典型架构:
code复制PDF -> 图片 -> Base64 -> 前端懒加载
↑
CDN缓存
结合Workflow实现:
PDF解析安全:
Base64传输安全:
X-Content-Type-Options: nosniffDocker部署方案:
dockerfile复制FROM mcr.microsoft.com/dotnet/aspnet:6.0
RUN apt-get update && \
apt-get install -y ghostscript libgdiplus
使用TopShelf创建Windows服务:
csharp复制class PdfService : ServiceControl
{
public bool Start(HostControl hostControl)
{
// 启动文件监视器
var watcher = new FileSystemWatcher();
watcher.Created += (s,e) => ProcessNewPdf(e.FullPath);
return true;
}
}
测试环境:i7-11800H/32GB RAM
| 页数 | 纯转换(ms) | +Base64(ms) | 内存占用(MB) |
|---|---|---|---|
| 1 | 120 | 145 | 15 |
| 10 | 980 | 1120 | 85 |
| 100 | 9200 | 10500 | 620 |
优化建议:
当需要更高性能时可以考虑:
服务器端渲染方案:
bash复制soffice --headless --convert-to png *.pdf
云服务方案:
但需要注意: