如何使用 .net 6 和 PdfSharpCore 在服务器端打印?

How can I print in server Side with .net 6 and PdfSharpCore?

提问人:V.d.S Wim 提问时间:3/24/2023 最后编辑:V.d.S Wim 更新时间:4/1/2023 访问量:476

问:

我想在服务器端打印,但我拥有的代码无法正常工作,并且在互联网上找不到任何解决方案。 我使用 nuget PdfSharpCore(版本 1.3.47)。 问题是我不知道如何将页面转换为可用于打印作业的位图或图像。 我到处添加评论来提供帮助。

这是我的代码:

using System;
using System.Drawing;
using System.Drawing.Printing;
using System.IO;
using PdfSharpCore.Pdf;
using PdfSharpCore.Pdf.IO;
/// <summary>
/// The following code takes in a byte array of a PDF file, a printer name, a job name
/// (optional), and a boolean flag for whether to print in color or black and white. It then
/// prints the PDF file using the specified printer.
/// </summary>
/// <param name="pdfBytes">
/// </param>
/// <param name="printerName">
/// </param>
/// <param name="jobName">
/// </param>
/// <param name="isColor">
/// </param>
public void PrintPdf(byte[] pdfBytes, string printerName, string? jobName = null, bool isColor = true)
{
            // Use a memory stream to read the PDF bytes
            using (var pdfStream = new MemoryStream(pdfBytes))
            {
                // Use PdfSharp to open the PDF document
                using (var doc = PdfReader.Open(pdfStream))
                {
                    // Check if we are running on Windows
                    if (OperatingSystem.IsWindows())
                    {
                        // Only execute the following code if running on Windows

                        // Use PrintDocument to manage printing
                        using (var pd = new PrintDocument())
                        {
                            // Set the printer name
                            pd.PrinterSettings.PrinterName = printerName;

                            // Check if printer exists
                            if (!pd.PrinterSettings.IsValid)
                            {
                                // If the specified printer is not valid, use the default printer
                                pd.PrinterSettings.PrinterName = PrinterSettings.InstalledPrinters[0];

                                // Log all possible printers
                                foreach (string printer in PrinterSettings.InstalledPrinters)
                                {
                                    Console.WriteLine(printer);
                                }
                            }

                            // Set the print job name (if provided) or default to "Print Job"
                            pd.DocumentName = jobName ?? "Print Job";

                            // Set print settings
                            pd.DefaultPageSettings.Landscape = false;
                            pd.DefaultPageSettings.Color = isColor;

                            // Zero-based index for current page
                            int currentPage = 0;

                            // Add a PrintPageEventHandler to handle the printing of each page
                            pd.PrintPage += (sender, args) =>
                            {
                                // Check if the operating system is Windows
                                if (OperatingSystem.IsWindows())
                                {
                                    // Get the current page and its size
                                    var page = doc.Pages[currentPage];
                                    var size = new Size((int)page.Width, (int)page.Height);

                                    // Check if the page stream is not null
                                    if (page?.Stream != null)
                                    {
                                        // Render the PDF page as an image and draw it onto the bitmap
                                        using (var pageStream = new MemoryStream(page.Stream.Value))
                                        {
                                            using (var bmp = new Bitmap(pageStream))
                                            {
                                                // Check if the graphics object is not null
                                                if (args?.Graphics != null)
                                                {
                                                    try
                                                    {
                                                        // Draw the image onto the graphics object
                                                        // within the page boundaries
                                                        args.Graphics.DrawImage(bmp, args.PageBounds);
                                                    }
                                                    catch (Exception ex)
                                                    {
                                                        // Handle any exceptions that occur while
                                                        // rendering the image
                                                        Console.WriteLine($"Error rendering PDF as image: {ex.Message}");
                                                    }
                                                }
                                                else
                                                {
                                                    Console.WriteLine("Graphics object is null.");
                                                }
                                            }
                                        }
                                    }
                                    else
                                    {
                                        Console.WriteLine("PDF Stream empty.");
                                    }

                                    // Move to the next page
                                    currentPage++;

                                    // Set HasMorePages to true if there are more pages to print
                                    if (args != null)
                                    {
                                        args.HasMorePages = currentPage < doc.PageCount;
                                    }
                                }
                                else
                                {
                                    // Code for other operating systems
                                }
                            };

                            // Execute the Print Event
                            pd.Print();
                        }
                    }
                    else
                    {
                        // Code for other operating systems
                    }
                }
            }
        }
打印 NET-6.0 服务器端 PDFsharpCore

评论

0赞 I liked the old Stack Overflow 3/28/2023
PDF 文件中的页面包含 postscript 样式的绘图说明列表。您需要一个可以将这些绘图指令渲染到位图或打印机上下文的库 - PDFsharp 无法做到这一点。服务器端打印到底有什么意义?
0赞 IvanMendoza 3/29/2023
在打印前存储 PDF 并在打印后删除 PDF 是否有限制?
0赞 IvanMendoza 3/29/2023
对您打印到网络打印机有用吗?

答:

1赞 I liked the old Stack Overflow 3/28/2023 #1

使用 PdfSharpCore,您无法将 PDF 转换为位图,也无法将 PDF 发送到打印机。

您将需要另一个库来将 PDF 页面转换为位图。图书馆推荐在 SO 上是一件困难的事情,所以我不会在这里推荐任何内容。

使用 PDFsharp(移植 PdfSharpCore 的库),您可以使用相同的代码同时创建 PDF 和打印。打印输出不能包含 PDF 页面中的元素,因为 PDFsharp 无法处理。我不知道你的PDF是从哪里来的。如果 PDF 是从您的代码创建的,这可能是您的一个选项。仅在 Windows 下有效的选项。

服务器端打印的一个缺点是打印输出将在服务器站点上生成,而不是在客户端站点上生成。许多网站只是提供 PDF 并让客户进行打印。

2赞 Shloime Rosenblum 4/1/2023 #2

您可以使用 Ghostscript.NET 打印 pdf。

您需要将 pdf 保存到临时文件并使用 ghostscript 库进行打印。

您需要将gsdll32.dll放在项目中的某个目录中,设置路径new GhostscriptVersionInfo("")

我没有测试颜色/灰度是否有效,可能是您需要在打印前将文件转换为灰度。而且我还不知道如何设置作业名称。

/// <summary>
/// The following code takes in a byte array of a PDF file, a printer name, a job name
/// (optional), and a boolean flag for whether to print in color or black and white. It then
/// prints the PDF file using the specified printer.
/// </summary>
/// <param name="pdfBytes">
/// </param>
/// <param name="printerName">
/// </param>
/// <param   name="jobName">
/// </param>
/// <param name="isColor">
/// </param>
public void PrintPdf(byte[] pdfBytes, string printerName, string? jobName = null, bool isColor = true)
{
            GhostscriptVersionInfo ghostscriptVersion = new GhostscriptVersionInfo("gs/gsdll32.dll");
            string inputFile = Path.GetTempFileName() + ".pdf";
            File.WriteAllBytes(inputFile, pdfBytes);
            try
            {


                using (GhostscriptProcessor processor = new GhostscriptProcessor(ghostscriptVersion, true))
                {
                    List<string> switches = new List<string>();
                    switches.Add("-empty");
                    switches.Add("-dPrinted");
                    switches.Add("-dDuplex");
                    if (isColor)
                    {
                        switches.Add("-sOutputICCProfile=default_cmyk.icc");
                    }
                    switches.Add("-dTumble=0");
                    switches.Add("-dBATCH");
                    switches.Add("-dNOPAUSE");
                    switches.Add("-dNOSAFER");
                    switches.Add("-dAutoRotatePages=/All");
                    switches.Add("-sDEVICE=mswinpr2");
                    switches.Add("-dNoCancel");
                    switches.Add("-sOutputFile=%printer%" + printerName);
                    switches.Add("-f");
                    switches.Add(inputFile);

                    processor.StartProcessing(switches.ToArray(), null);
                }
            }
            catch (Exception e)
            {
                MessageBox.Show("Error printing file. \nOriginal message: " + e.Message);
            }
            finally
            {
                if (File.Exists(inputFile))
                {
                    File.Delete(inputFile);
                }
            }
        }           
}

评论

1赞 I liked the old Stack Overflow 4/4/2023
问题是关于使用 PdfSharpCore 进行打印。这个答案为游戏带来了两个新库,Ghostscript.NET 和 Ghostscript。更复杂的是,这两个库使用不同的许可证。PDFsharp 的许可证非常宽松,对于许多项目来说,具有更严格许可证的库将不是一个选择。
1赞 Shloime Rosenblum 4/19/2023
虽然这可能是也可能不是 OP 正在寻找的答案,但它肯定会对遇到类似问题的其他人有所帮助