Преобразование внешних ссылок в PDF для ссылки на встроенное вложение в iTextSharp - PullRequest
0 голосов
/ 16 октября 2018

У меня немного странное задание.Мы собираемся закрыть довольно большое внутреннее решение и хотим выполнить одноразовый экспорт данных, которые в нем хранятся.

Решение генерирует отчеты в формате PDF.Эти PDF-файлы в основном содержат текст, но также содержат изображения.Изображения - это ссылки, которые при активации открывают браузер и указывают на полноразмерную версию изображения.

Поскольку мы собираемся закрыть базовую систему, внешние ссылки на полноразмерные изображениятакже перестанет работать.

По ряду странных причин мы имеем ограниченный контроль над самой генерацией отчетов, поэтому мы в основном ограничены выполнением последующей обработки отчетов.

План, который я разработал до сих пор, состоит в том, чтобы генерировать все необходимые отчеты из системы и обрабатывать их через iTextSharp.«Все», что я пытаюсь добиться - это обработать каждый PDF-файл и:

  1. Поиск внешних ссылок
  2. Загрузить полноразмерное изображение, на которое указывает ссылка, и прикрепитьэто в PDF как встроенный файл
  3. Удалите исходную внешнюю ссылку и замените ее ссылкой на соответствующий встроенный ресурс

Я не знаком с базовой структурой PDF-файловтак что я пытаюсь работать с iTextSharp.Однако до сих пор мне удалось (1) и (2) разобраться.Но я борюсь с (3):

Я в основном использую этот в качестве подтверждающего документа, но я не совсем достигаю своей цели.

Этомой код, где я обрабатываю каждую аннотациюКак примечание, я использую iTextSharp версии 5.5.13:

if (AnnotationDictionary.Get(PdfName.A) != null)
{
    var annotActionObject = AnnotationDictionary.Get(PdfName.A);
    var AnnotationAction = (PdfDictionary)(annotActionObject.IsIndirect() ? PdfReader.GetPdfObject(annotActionObject) : annotActionObject);

    var type = AnnotationAction.Get(PdfName.S);
    //Test if it is a URI action
    if (type.Equals(PdfName.URI))
    {
        //Attach the downloaded file
        PdfFileSpecification pfs = PdfFileSpecification.FileEmbedded(writer, embFile.Path, embFile.Description, null);
        pfs.AddDescription(embFile.Description, false);
        writer.AddFileAttachment(pfs);

        //Removing old annotation
        AnnotationAction.Remove(PdfName.A);
        AnnotationDictionary.Remove(PdfName.A);

        PdfDestination destination = new PdfDestination(PdfDestination.FIT);
        destination.AddFirst(new PdfNumber(1));

        var target = new PdfTargetDictionary(true);
        target.EmbeddedFileName = embFile.Name;

        PdfAction action = PdfAction.GotoEmbedded(null, target, destination, true);

        AnnotationDictionary.Put(PdfName.D, action.Get(PdfName.D));
        AnnotationAction.Put(PdfName.D, action.Get(PdfName.D));
    }
}

Для некоторых это, скорее всего, довольно очевидно, почему он не работает:)

Сейчас все работаетпросто отлично, и он выплевывает PDF на другом конце.Как уже упоминалось, изображения в PDF больше не имеют активной ссылки, и все вложенные файлы встраиваются, как и ожидалось.Тем не менее, ссылка на встроенный ресурс не работает, и нигде нет указаний на это.

Все отзывы приветствуются.Спасибо.

1 Ответ

0 голосов
/ 18 октября 2018

Как отмечено в комментариях, вы можете ссылаться только на встроенный PDF-файл.

Вы изменяете только запись D.Вам необходимо переопределить всю запись A, но не забудьте сохранить местоположение цели.

Вот быстрый POC, который я создал:

PdfReader reader = new PdfReader(INPUT_FILE);
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(OUTPUT_FILE));

    PdfFileSpecification fs = PdfFileSpecification.fileEmbedded(stamper.getWriter(), null, "EmbeddedFile.pdf", FileUtils.readFileToByteArray(new File(INPUT_FOLDER + "embeddedfile.pdf")));
    fs.addDescription("specificname", false);
    stamper.getWriter().addFileAttachment(fs);
    PdfTargetDictionary targetDictionary = new PdfTargetDictionary(true);
    targetDictionary.setEmbeddedFileName("specificname");


    PdfDestination dest = new PdfDestination(PdfDestination.FIT);
    dest.addFirst(new PdfNumber(1));
    PdfAction action = PdfAction.gotoEmbedded(null, targetDictionary, dest, true);

    PdfDictionary page = reader.getPageN(1);
    PdfArray annotations = page.getAsArray(PdfName.ANNOTS);


    for(int x=0;x<annotations.size();x++) {
        PdfDictionary annotation = annotations.getAsDict(x);
        PdfArray location = annotation.getAsArray(PdfName.RECT);
        action.put(PdfName.RECT,location);
        annotation.put(PdfName.A, action);
    }


    stamper.close();

INPUT_FILE указывает на оригиналOUTPUT_FILE указывает на то место, куда вы хотите его сохранить, а INPUT_FOLDER + "embeddedFile.pdf" указывает на файл PDF, на который хотите сослаться аннотацию.

Итак, action - это ваше новое действие, которое указывает навстроенный файл PDF (и только файл PDF).Мы просто заменим запись A старой аннотации на action.Тогда мы обязательно установим местоположение action на местоположение старой аннотации.

...