基于iText的PDF对象计数、流替换及Filter修改技术咨询
基于iText的PDF流解密与修改解决方案
针对你用iText处理PDF解密的需求,以下是三个问题的具体解决方法:
(1) 获取PDF对象总数
使用PdfReader的GetXrefSize()方法可以获取PDF交叉引用表的大小,这对应PDF对象的最大编号(PDF对象编号从1开始),可直接用来遍历所有对象,替代硬编码的1000限制:
var pdf = new PdfReader(file); int totalObjects = pdf.GetXrefSize(); for (int i = 1; i < totalObjects; i++) { PdfObject obj = pdf.GetPdfObject(i); // 后续处理逻辑 }
(2) 替换PDF中的流数据
通过PRStream的SetData()方法可直接替换流内容,最后用PdfStamper将修改后的PDF写出:
// 在遍历到流对象的代码块中 PRStream encryptedStream = (PRStream)pdf.GetPdfObject(i); byte[] encryptedBytes = PdfReader.GetStreamBytesRaw(encryptedStream); byte[] decryptedContent = VendorDecrypt.__DecryptHelper(DecryptFileFormat.Buffer, key, random, encryptedBytes); // 替换流内容 encryptedStream.SetData(decryptedContent); // 遍历完成后保存修改后的PDF using (var stamper = new PdfStamper(pdf, new FileStream(outputFile, FileMode.Create))) { // stamper会自动处理所有修改 }
(3) 移除Filter中的"VendorPDFEncrypt"并更新Length
先获取流的字典对象,读取原Filter数组并创建新数组移除目标过滤器,再将新数组放回字典。流的Length会在调用SetData()时自动计算更新,无需手动设置:
// 在替换流内容的代码块中 PRStream encryptedStream = (PRStream)pdf.GetPdfObject(i); PdfDictionary streamDict = encryptedStream.GetDict(); // 获取原Filter数组 PdfArray filterArray = streamDict.GetAsArray(PdfName.FILTER); if (filterArray != null) { List<PdfObject> newFilters = new List<PdfObject>(); foreach (PdfObject filter in filterArray) { // 跳过VendorPDFEncrypt过滤器 if (!PdfName.VENDORPDFENCRYPT.Equals(filter)) { newFilters.Add(filter); } } // 设置新的Filter数组 streamDict.Put(PdfName.FILTER, new PdfArray(newFilters)); } // 替换流内容后,Length会自动更新 encryptedStream.SetData(decryptedContent);
完整修改后的代码示例
var pdf = new PdfReader(file); int totalObjects = pdf.GetXrefSize(); for (int i = 1; i < totalObjects; i++) { PdfObject obj = pdf.GetPdfObject(i); if (obj != null && obj.IsStream()) { PRStream encryptedStream = (PRStream)obj; byte[] encryptedBytes = PdfReader.GetStreamBytesRaw(encryptedStream); byte[] decryptedContent = VendorDecrypt.__DecryptHelper(DecryptFileFormat.Buffer, key, random, encryptedBytes); // 修改Filter数组 PdfDictionary streamDict = encryptedStream.GetDict(); PdfArray filterArray = streamDict.GetAsArray(PdfName.FILTER); if (filterArray != null) { List<PdfObject> newFilters = new List<PdfObject>(); foreach (PdfObject filter in filterArray) { if (!PdfName.VENDORPDFENCRYPT.Equals(filter)) { newFilters.Add(filter); } } streamDict.Put(PdfName.FILTER, new PdfArray(newFilters)); } // 替换流内容,自动更新Length encryptedStream.SetData(decryptedContent); } } // 保存修改后的PDF using (var stamper = new PdfStamper(pdf, new FileStream("output.pdf", FileMode.Create))) { // 无需额外操作,stamper会处理所有修改 }
内容的提问来源于stack exchange,提问作者Tom Xue
相关产品推荐
相关产品推荐

