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

702 views Asked by At

I would like to print on Server side but the code that I have will not work properly and don't find any solution on the internet. I use the nuget PdfSharpCore (version 1.3.47). The problem is I don't know how to translate a page to a bitmap or image that can be used for the print job. I added everywhere comments to help.

Here is my code :

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
                    }
                }
            }
        }
2

There are 2 answers

0
I liked the old Stack Overflow On

With PdfSharpCore, you cannot convert PDF to bitmaps, nor can you send PDF to a printer.

You will need another library to convert the PDF pages to bitmaps. Library recommendations are a difficult matter on SO, so I will not recommend any here.

With PDFsharp, the library that PdfSharpCore was ported from, you can use the same code to create PDFs and print at the same time. The printout cannot contain elements from PDF pages because PDFsharp cannot handle that. I don't know where your PDFs are coming from. If the PDFs are created from your code, this may be an option for you. An option that works under Windows only.

One disadvantage of server-side printing is that the printout will be generated on the server site, not the client site. Many websites just deliver PDFs and let the client do the printing.

2
Shloime Rosenblum On

You can print your pdf with Ghostscript.NET.

You need to save your pdf to a temp file and print with the ghostscript library.

You need to put the gsdll32.dll in a directory in the project in set the path in new GhostscriptVersionInfo("")

I didn't test if the color/grayscale works it may be you need to convert the file to grayscale before printing. And I don't know yet how to set the job name.

/// <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);
                }
            }
        }           
}