【问题标题】:Print PDF using GhostScript使用 GhostScript 打印 PDF
【发布时间】:2013-12-11 16:16:18
【问题描述】:

在以下问题上,我需要您的支持,因为它让我有一段时间了。我们有一个小的c# 实用程序,它使用GhostScript 打印给定PDF。此打印按预期打印,但未能保留页面格式。但是,当我切换Adobe Acrobat 代替GhostScript 时,页面会按预期打印。所以我想,我在 GhostScript 的命令行参数上犯了一些明显的错误。

背景

以下是核心 c# 逻辑,它在每个页面上打印具有不同样式的给定 PDF 文件。给定的 PDF 文件有页面;

  1. 字体样式和颜色不一致
  2. 有些页面的字体大小正常,而其他页面的字体则超小
  3. 一些页面有推荐的边距,但其他页面的边距非常小
  4. 部分页面为彩色,其余为灰色。
  5. 有些页面是横向的,而另一些是纵向的

简而言之,我尝试打印的 PDF 只不过是众多具有不同字体样式、大小和边距的小型 pdf 文档的合并(将单个 pdf 合并为一个大 pdf)。

问题

以下逻辑使用GhostScript(v9.02) 打印PDF 文件。尽管以下逻辑打印任何给定的 PDF,但它无法保留页面格式,包括 页眉、页脚、字体大小、边距、方向(我的 pdf 文件有横向和纵向页面)。

有趣的是,如果我使用 acrobat reader 打印相同的 PDF,那么它将按预期与所有页面级格式一起打印。

PDF 样本:First sectionSecond section

  void PrintDocument()
    {
         var psInfo = new ProcessStartInfo();
                psInfo.Arguments =
                    String.Format(
                        " -dPrinted -dBATCH -dNOPAUSE -dNOSAFER -q -dNumCopies=1 -sDEVICE=ljet4 -sOutputFile=\"\\\\spool\\{0}\" \"{1}\"",
                        GetDefaultPrinter(), @"C:\PDFOutput\test.pdf");
                psInfo.FileName = @"C:\Program Files\gs\gs9.10\bin\gswin64c.exe";
                psInfo.UseShellExecute = false;

        using (var process= Process.Start(psInfo))
        {
            process.WaitForExit();
        }
    }

【问题讨论】:

  • 只是为了确保我理解您的问题:您的问题是否与合并 PDF 文件(而不是实际创建或真正打印 PDF)有关?
  • @elgonzo,问题在于打印而不是合并。
  • 现在我很困惑...如果只是关于打印而不是合并 PDF,您为什么要谈论 Acrobat 以及将单个 PDF 合并到一个更大的 PDF 中?
  • 从我们项目的经验来看,GhostScript/GhostPDL (PCL)/GhostXPS 实际上与字体支持非常不一致,除非是面向ghost的DTP核心,否则都不应该在生产周期中使用。
  • 也许您应该报告问题,以便解决问题。据我所知,Ghostscript 完全支持所有字体类型。当然,如果您不嵌入或不提供字体,那么您将获得替代品,但这不是应用程序的错。

标签: c# pdf printing ghostscript postscript


【解决方案1】:

我想你之前问过这个问题,从你的代码示例中也很清楚你使用的是 GSView,而不是 Ghostscript

现在,虽然 GSView 确实使用 Ghostscript 来完成繁重的工作,但令人担心的是您无法区分这两个应用程序。

尽管您现在至少设法引用了 Ghostscript 版本,但您仍然没有提供可供查看的示例 PDF 文件,也没有提供命令行。您还需要提供一个命令行(不,我不准备通过阅读您的代码来组装它)并且您应该从命令行尝试这个,而不是在您自己的应用程序中,以表明它不是您的应用程序制作错误。

您应该考虑将 Ghostscript 升级到当前版本。

请注意,快速阅读您的代码表明您正在指定一些命令行选项(例如 -dPDFSETTINGS),这些选项仅适用于将文件转换为 PDF,不适用于任何其他目的(例如打印)。

所以正如我之前所说,提供一个样本文件来重现问题,以及一个导致问题的命令行(最好是 Ghostscript 命令行)。知道您使用的是哪台打印机可能也很有用,尽管我不太可能有一个副本来测试。

【讨论】:

  • 感谢您的回复。 (1) 看了之后,我的印象是GsView是用GhostScript来打印PDF的。我想我需要回顾一下我的理解。 (2) 你能帮助我或指导我如何在没有 GSView 的情况下使用 GhostScript 打印 PDF 吗? (3) 关于示例 PDF,我可以向您保证一件事,该文档包含 NDA 和财务信息,因此我无法共享它。对于那个很抱歉。但肯定的是,我会寻找一些过时/旧的 PDF 文件(4)你是绝对正确的,由于缺乏知识,我正在尝试使用随机命令行选项。
  • 根据您的建议,我修改了我的初始帖子和我的应用程序,它取代了 GSView 的使用,现在它完全依赖于 GhostScript。不过,这个问题继续持有良好。有什么帮助吗??
  • GSView确实使用了Ghostscript,但是命令行参数不一样。如果您无法共享导致问题的文档,我将无能为力。也许您可以创建一个可以共享的。要使用 Ghostscript 打印文件(在 Windows 下),您需要使用 mswinpr2 设备。
  • 我附上了文件样本。实际上,我们在打印之前加入这些文件(一个接一个)。但是这个加入过程是由第三方完成的,因此我无法控制它。但是,这些单独的文档足以重现该问题。另外,正如您所建议的,我愿意使用 GhostScript 或 GS​​View 和 GhostScript 来打印文档。
  • app1.pdf 坏了,它包含 2 个 %%EOF 和 2 个 startxref 指令(应该只有 1 个)。 Ghostscript 在读取文件时会修复此问题。主要问题是这两个文件都使用了它们不提供的字体。每当发生这种情况时,您获得字体替换,即使使用 Acrobat 也是如此。 Acrobat 行为不同的原因是,在安装时,它会将 Windows 字体文件夹中的字体添加到它可以使用的字体中。您也可以通过添加 -sFONTPATH= 并可能通过修改 fontmap.gs 文件(这将需要您下载 GS 源)来为 Ghostscript 执行此操作
【解决方案2】:

答案 - 2013 年 16 月 12 日更新

我设法修复了它,如果它可以帮助其他人,我想附上工作解决方案。特别感谢“KenS”,因为他花了很多时间指导我。

总而言之,我最终决定使用 GSView 和 GhostScript 来打印 PDF 以绕过 Adob​​e。核心逻辑如下;

 //PrintParamter is a custom data structure to capture file related info
private void PrintDocument(PrintParamter fs, string printerName = null)
        {
            if (!File.Exists(fs.FullyQualifiedName)) return;

            var filename = fs.FullyQualifiedName ?? string.Empty;
            printerName = printerName ?? GetDefaultPrinter(); //get your printer here

            var processArgs = string.Format("-dAutoRotatePages=/All -dNOPAUSE -dBATCH -sPAPERSIZE=a4 -dFIXEDMEDIA -dPDFFitPage -dEmbedAllFonts=true -dSubsetFonts=true -dPDFSETTINGS=/prepress -dNOPLATFONTS -sFONTPATH=\"C:\\Program Files\\gs\\gs9.10\\fonts\" -noquery -dNumCopies=1 -all -colour -printer \"{0}\" \"{1}\"", printerName, filename);
            try
            {

                var gsProcessInfo = new ProcessStartInfo
                                        {
                                            WindowStyle = ProcessWindowStyle.Hidden,
                                            FileName = gsViewEXEInstallationLocation,
                                            Arguments = processArgs
                                        };
                using (var gsProcess = Process.Start(gsProcessInfo))
                {

                    gsProcess.WaitForExit();

                }

        }

【讨论】:

    【解决方案3】:

    你可以使用GSPRINT

    我已经设法通过仅将 gsprint.exe/gswin64c.exe/gsdll64.dll 复制到一个目录中并从那里启动它来使其工作。

    示例代码:

        // This uses gsprint (mind the paths)
        private const string gsPrintExecutable = @"C:\gs\gsprint.exe";
        private const string gsExecutable = @"C:\gs\gswin64c.exe";
    
        string pdfPath = @"C:\myShinyPDF.PDF"
        string printerName = "MY PRINTER";
    
    
        string processArgs = string.Format("-ghostscript \"{0}\" -copies=1 -all -printer \"{1}\" \"{2}\"", gsExecutable, printerName, pdfPath );
    
                var gsProcessInfo = new ProcessStartInfo
                                        {
                                            WindowStyle = ProcessWindowStyle.Hidden,
                                            FileName = gsPrintExecutable ,
                                            Arguments = processArgs
                                        };
                using (var gsProcess = Process.Start(gsProcessInfo))
                {
    
                    gsProcess.WaitForExit();
    
                }
    

    【讨论】:

      【解决方案4】:

      Process.Start() 中尝试以下命令:

      gswin32c.exe -sDEVICE=mswinpr2 -dBATCH -dNOPAUSE -dNOPROMPT -dNoCancel -dPDFFitPage -sOutputFile="%printer%\\[printer_servername]\[printername]" "[filepath_to_pdf]"
      

      在 C# 中应该是这样的:

      string strCmdText = "gswin32c.exe -sDEVICE=mswinpr2 -dBATCH -dNOPAUSE -dNOPROMPT -dNoCancel -dPDFFitPage -sOutputFile=\"%printer%\\\\[printer_servername]\\[printername]\" \"[filepath_to_pdf]\"";
      System.Diagnostics.Process.Start("CMD.exe", strCmdText);
      

      这会将指定的 PDF 文件放入打印队列。

      注意- gswin32c.exe 必须与 C# 程序位于同一目录中。我没有测试过这段代码。

      【讨论】:

        猜你喜欢
        • 2017-11-24
        • 1970-01-01
        • 2012-06-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-19
        • 2014-11-25
        相关资源
        最近更新 更多