能否使用pikepdf解密Azure Blob存储中非UTF-8编码的PDF流?
问题原因
这个UnicodeDecodeError和PDF编码、pikepdf的编码支持能力没有任何关系,是入参类型使用错误导致的:
download_blob().readall()返回的是PDF的原始二进制字节数据pikepdf.Pdf.open()接收到bytes类型入参时,会默认将其作为文件路径的字节序列尝试解码为字符串路径,不会直接把bytes当做PDF内容解析,解码过程中遇到非UTF-8的二进制字节就会抛出你看到的报错。- pikepdf本身完全支持处理所有标准加密PDF,和PDF内部用什么文本编码、文件存在本地还是Azure Blob存储没有关联,不存在“无法解密非UTF-8编码PDF流”的问题。
修复方法
两种实现方式都可以解决问题,选其一即可:
方法1:用内存字节流直接读取(无需写临时加密文件)
导入io模块,将下载得到的二进制字节包装为BytesIO类文件对象,pikepdf识别到类文件对象入参时会直接读取流内的PDF内容,不会按文件路径解析:
import io # 原有Blob下载逻辑保留 streamdownloader = blob_client.download_blob().readall() # 新增包装流的步骤 pdf = pikepdf.Pdf.open(io.BytesIO(streamdownloader), password=password) # 后续保存、读取逻辑无需改动 pdf.save(dec)
方法2:先落地加密临时文件再读取
如果不想走内存处理,可以先把Blob下载的加密PDF二进制内容写到本地临时文件,再传本地文件路径给pikepdf打开:
streamdownloader = blob_client.download_blob().readall() temp_encrypted_path = "C:/Users/python-test/source_dir/temp_encrypted.pdf" # 先写加密文件到本地 with open(temp_encrypted_path, 'wb') as temp_f: temp_f.write(streamdownloader) # 再从本地路径打开加密PDF pdf = pikepdf.Pdf.open(temp_encrypted_path, password=password) pdf.save(dec)
其他优化提示
- 你当前使用的
PyPDF2.PdfFileReader是PyPDF2旧版本的废弃API,升级PyPDF2后会直接报属性错误,替换为PyPDF2.PdfReader即可,对应的页数获取从pdfReader.numPages改为len(pdfReader.pages)。 - 打开本地文件建议使用
with上下文管理器,避免手动关闭文件遗漏导致的句柄泄露问题。
内容的提问来源于stack exchange,提问作者Eliot Kim
相关产品推荐
相关产品推荐

