Base64转PDF必须严格走Convert.FromBase64String→byte[]→File.WriteAllBytes三步,禁用文本编码、URL污染未清洗、Data URL前缀未剔除、日志误打字节数组等均会导致PDF损坏。

Base64字符串转PDF文件:直接写入磁盘最稳
能还原,但必须走 Convert.FromBase64String() → byte[] → 文件流写入三步,跳过任意一环都可能生成损坏PDF。常见错误是把解码后字节当文本处理(比如用 Encoding.UTF8.GetString() 再转回来),PDF二进制不是文本,不能进编码/解码循环。
- 确认Base64字符串没被URL编码污染(如
%2B替代+、%3D替代=),先用WebUtility.UrlDecode()清洗再解码 - 解码失败抛
FormatException通常因为长度非4的倍数、含非法字符(空格、换行、中文),别硬吞异常,加try/catch并记录原始字符串前32位用于排查 - 写入时用
File.WriteAllBytes(path, bytes),别用StreamWriter或FileStream.WriteAsync()配合不带FileMode.Create的方式——容易残留旧内容或截断
内存中还原PDF并回显给前端:别碰Response.OutputStream
ASP.NET Core 下直接操作 Response.Body 容易触发“response already started”错误;.NET Framework 里用 Response.OutputStream 则可能因缓冲区未刷出导致PDF打开空白。正确路径是统一走 IActionResult 返回 FileResult。
- Core项目优先用
File(byte[], "application/pdf", "xxx.pdf"),框架自动设Header、处理流生命周期 - 如果PDF需动态生成(如合并后临时拼装),用
MemoryStream包住字节再传给File(),别用ToArray()多拷贝一次——大文件(>5MB)会陡增GC压力 - 避免在Action里调
Response.StatusCode = 200或手动写Header,和File()冲突,Header会被覆盖或报错
Base64开头有data:application/pdf;base64,怎么办
这是Data URL格式,不是纯Base64,直接喂给 Convert.FromBase64String() 必崩。必须切掉前缀,只留后面那段编码体。
- 用
string.IndexOf(',') + 1定位分隔逗号,再Substring()截取,比正则快且无编译开销 - 注意有些前端库(如某些Vue PDF预览组件)会自动补前缀,而后端又自己加一遍,导致双重前缀,解码前先检查是否已含
data: - 若不确定来源,写个安全提取函数:
var base64 = input.Contains(",") ? input.Substring(input.IndexOf(",") + 1) : input;
PDF打开显示“已损坏”或“无法打开”的典型原因
90%不是Base64问题,而是字节被意外修改。重点查这三处:
- 日志打印时用了
Console.WriteLine(bytes)—— 这会调ToString()输出类型名,不是内容!调试请用Convert.ToBase64String(bytes).Substring(0, 50)看头 - 数据库字段类型为
varchar或nvarchar存Base64,入库前没过滤 \0、\r\n 等控制字符,导致截断或注入换行破坏编码结构 - 反向操作(PDF→Base64)时用了
File.ReadAllText()读PDF文件——这是致命错误,PDF必须用File.ReadAllBytes()读,否则从第一个\x00就开始丢数据
Base64和PDF之间没有“中间态”,只有完整字节流。任何试图把它当字符串切、替换、拼接、记录日志而不加防护的操作,都在悄悄破坏它。



















