Печать PDF-файлов в .NET Core с помощью System.Drawing.Printing

Я печатаю файлы PDF, конвертируя каждую страницу в изображение PNG с помощью PDFiumSharp. Затем я рисую это изображение в Graphics.

private void PrintPage(object sender, PrintPageEventArgs ev)
{
    ev.Graphics.DrawImage(images[pageNum], ev.Graphics.VisibleClipBounds);
    pageNum++;
    if (pageNum == images.Count)
    {
        ev.HasMorePages = false;
    }
    else
    {
        ev.HasMorePages = true;
    }
}

public void Print()
{
    printDocument.PrintPage += new PrintPageEventHandler(PrintPage);
    pageNum = 0;

    if (printDocument.PrinterSettings.IsValid)
    {
        printDocument.Print();
    }
    else
    {
        throw new Exception("Printer is invalid.");
    }
}

Проблема в том, что принтер получает очень большие данные и весь процесс работает медленно. Я пробовал использовать команду lpr в Windows. Он работает напрямую с файлами PDF, но мое приложение должно поддерживать двустороннюю печать, другой источник бумаги и т. Д., Что недоступно в lpr.

Как я могу распечатать PDF-файл с помощью System.Drawing.Printig (или чего-то еще, что предлагает аналогичные функции) без преобразования в изображение? Я использую .NET Core 3.1, мое приложение должно быть кроссплатформенным.


person Jacek Adamus    schedule 20.08.2020    source источник
comment
Вы нашли альтернативное решение?   -  person uyusuk    schedule 09.12.2020
comment
Нет, к сожалению нет. В конце концов, я решил остановиться на PNG, PDFiumSharp и Drawing.Printing. Это не очень быстро и генерирует большие файлы, но печать в Windows и Linux работает нормально.   -  person Jacek Adamus    schedule 18.12.2020


Ответы (1)


Собственно, вам нужно выбрать любые 2 из 3:

  1. Отправляйте данные на принтер напрямую без растровых изображений
  2. Используйте System.Drawing.Printing
  3. Кроссплатформенность

Например, 1 и 2 нормально работают в Windows. Существуют кроссплатформенные библиотеки PDF, которые могут анализировать и печатать PDF непосредственно в System.Drawing.Graphics. Взгляните на этот образец .

Проблема в том, что System.Drawing плохо работает в Linux и macOS. Он использует libgdiplus, и эта реализация имеет много практических проблем.
Например, libgdiplus не обрабатывает обтравочные контуры достаточно хорошо. Я исправил там несколько связанных проблем (# 545, # 547, # 552) и нашел серьезные блокираторы для дальнейших улучшений.

Первый - это мейнтейнеры. Они не отвечали на вопросы и просматривали простые запросы на включение по месяцам. Похоже, что Microsoft не очень заинтересована в этом проекте.

Второй блокиратор - это внутренняя архитектура. Есть две старые реализации регионов (на основе растровых изображений и прямоугольников), которые следует пересмотреть. Однако без связи с сопровождающими также невозможно вносить архитектурные изменения.

Думаю, у вас есть 2 варианта:

  1. Используйте библиотеку PDF, которая может печатать в System.Drawing.Graphics без промежуточных изображений (как в примере выше). Он будет нормально работать в Windows. В Linux вам понадобится:

    • fix found issues in libgdiplus yourself, use customized version in your production.
    • преобразовать PDF в изображения, а затем распечатать растровые изображения.
  2. Не используйте System.Drawing.Printing

person Vitaliy Shibaev    schedule 26.11.2020
comment
Мое приложение .net core 5.0 работает на Linux ARM (точнее, Raspberry Pi), принтер подключается через USB и использует CUPS (он может печатать командой lp), знаете ли вы, как я могу отправить необработанные данные на принтер в .NET Core? Мы будем очень признательны, если есть некоторый код (основные классы / методы, которые будут использоваться). Спасибо. - person James L.; 28.01.2021
comment
@JamesL, вы имеете в виду вызов команды lp из вашего .NET-приложения? Вы можете сделать это с помощью класса System.Diagnostics.Process. Для более комплексного подхода рассмотрите этот вопрос: stackoverflow.com/questions/63347725/. Вы можете попросить совета у его автора, Ginger Ninja (stackoverflow.com/users/6552757/ginger-ninja). - person Vitaliy Shibaev; 29.01.2021
comment
Мой текущий способ - это именно вызов команды lp из .NET Core, она выполняет свою работу, но включает внепроцессные вызовы, которые влияют на производительность, мне интересно, есть ли библиотека, написанная на C # на .Net Core, для прямой отправки команд в Принтер IPP для печати, я поискал на сайте cups.org, есть реализации клиента IPP, написанные Java / Go / Python / Rust и т. Д., Я не нашел никаких реализаций .NET Core. - person James L.; 30.01.2021