Ошибка при попытке распаковать поток в PDF - PullRequest
0 голосов
/ 01 октября 2019

Я пытаюсь распаковать поток из объекта 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??. Этот поток добавлен в Stream.file в консольном приложении C #.

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.

Iхотелось бы, как декодировать этот поток с помощью кода .net, если это возможно.

Спасибо.

1 Ответ

2 голосов
/ 02 октября 2019

Основная проблема состоит в том, что класс DeflateStream может декодировать голый сжатый поток FLATE (согласно RFC 1951 ), но фактически отображается содержимое потоков PDF с фильтром FlateDecode в формате сжатых данных ZLIB (согласно RFC 1950 ) упаковка FLATE сжатые данные.

Чтобы исправить это, достаточно отбросить двухбайтовый заголовок ZLIB.

Другая проблема стала ясна в вашем первом примере документа: этот документ был зашифрован, поэтому перед декодированием FLATE содержимое потока в нем необходимо расшифровать.

Удалить заголовок ZLIB, чтобы получить данные, закодированные в FLATE

Класс DeflateStream может декодировать голый сжатый поток FLATE (согласно RFC 1951 ), но содержимое потоков PDF с фильтром FlateDecode фактически представлено в ZLIBСжатый формат данных (согласно RFC 1950 ) упаковка FLATE сжатые данные.

К счастью, довольно легко перейти к кодированию FLATE dПри этом нужно просто отбросить первые два байта. (Строго говоря, между ними и закодированными 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

Перед тем как распаковать содержимое потока, вам необходимо расшифровать их.

...