尝试解压缩 PDF 流时出错

Error while trying to decompress stream in PDF

我正在尝试从 file 中的 PDF 对象解压缩流:

 4 0 obj
<< 
/Filter /FlateDecode
/Length 64
>>
stream
xœs
QÐw34V02UIS0´0P030PIQÐpÉÏKIUH-.ITH.-*Ê··×TÉRp
á T‰
Ê
endstream
endobj

我将此流以与原始文件相同的格式复制粘贴到名为 Stream.file

的文件中
xœs
QÐw34V02UIS0´0P030PIQÐpÉÏKIUH-.ITH.-*Ê··×TÉRp
á T‰
Ê

此流应转换为:Donde esta curro??。在 C# 控制台应用程序中将该流添加到 Stream.file

using System.IO;
using System.IO.Compression;

namespace Filters
{
    public static class FiltersLoader
    {
        public static void Parse()
        {
            var bytes = File.ReadAllBytes("Stream.file");
            var originalFileStream = new MemoryStream(bytes);

            using (var decompressedFileStream = new MemoryStream())
            using (var decompressionStream = new DeflateStream(originalFileStream, CompressionMode.Decompress))
            {
                decompressionStream.CopyTo(decompressedFileStream);
            }    
        }
    }
}

但是在尝试复制时出现异常:

The archive entry was compressed using an unsupported compression method.

如果可能的话,我想知道如何使用 .net 代码解码此流。

谢谢。

主要问题是 DeflateStream class 可以解码裸 FLATE 压缩流(根据 RFC 1951) but the content of PDF streams with FlateDecode filter actually is presented in the ZLIB Compressed Data Format (as per RFC 1950wrapping FLATE 压缩数据。

要解决此问题,只需删除 two-byte ZLIB header。

另一个问题在您的第一个示例文档中变得清晰:该文档已加密,因此在 FLATE 解码之前必须解密其中的流内容。

###Drop ZLIB header 以获得 FLATE 编码数据

DeflateStream class 可以解码裸 FLATE 压缩流(根据 RFC 1951) but the content of PDF streams with FlateDecode filter actually is presented in the ZLIB Compressed Data Format (as per RFC 1950wrapping FLATE 压缩数据。

幸运的是,跳转到其中的 FLATE 编码数据非常容易,只需删除前两个字节即可。 (严格来说,它们和 FLATE 编码数据之间可能有一个 字典标识符 ,但这似乎很少使用。)

对于您的代码:

var bytes = File.ReadAllBytes("Stream.file");
var originalFileStream = new MemoryStream(bytes);

originalFileStream.ReadByte();
originalFileStream.ReadByte();

using (var decompressedFileStream = new MemoryStream())
using (var decompressionStream = new DeflateStream(originalFileStream, CompressionMode.Decompress))
{
    decompressionStream.CopyTo(decompressedFileStream);
}   

###如果是加密PDF,先解密

您的第一个示例文件 pdf-test.pdf 已加密,如预告片中存在的 Encrypt 条目所示:

trailer
<</Size 37/Encrypt 38 0 R>>
startxref
116
%%EOF

因此,在解压缩流内容之前,您必须对其进行解密。