GhostScript 在特定 PDF 文档上生成空白 PDF 文件

GhostScript generates a blank PDF file on a specific PDF document

我正在使用 GhostScript(当前为 9.27)在我的应用程序上减小 PDF 文件的大小,然后再将它们上传到文件服务器。 我面临的问题是一些 PDF 文件被转换为空白 PDF 文件,但是,如果我用 Adob​​e Acrobat 打开原始 PDF 文件并保存它然后执行我的 GhostScript 例程它运行正常,PDF 显示并且是正确 "compressed"(质量降低)。

我尝试了不同的 PDF 设置,但我想要的是 /ebook,所以我想让它以电子书质量工作。 我正在使用 GhostScript Wrapper(post 这里的代码),我调用的函数是:

RunGS("-dQUIET", "-dBATCH", "-dNOPAUSE", "-dNOGC", "-dPDFSETTINGS=/ebook", , "-sDEVICE=pdfwrite", "-sOutputFile=" & OUTPUT_FILE, INPUT_FILE)

当最终结果是一个空白的 PDF 文件并且 returns 出现此错误时,需要比平时更长的时间:

我刚刚注意到我收到错误回调...它说:

GhostScriptUnrecoverable 错误,退出代码 -100

这是非工作文件(原始文件):https://docdro.id/YuZslRm

这是开始使用 Acrobat 保存后的文件,效果很好:https://docdro.id/cAoUCS5

这里是包装器,以防万一:

模块 GhostscriptDllLib

Private Declare Function gsapi_new_instance Lib "gsdll32.dll" _
  (ByRef instance As IntPtr, _
  ByVal caller_handle As IntPtr) As Integer

Private Declare Function gsapi_set_stdio Lib "gsdll32.dll" _
  (ByVal instance As IntPtr, _
  ByVal gsdll_stdin As StdIOCallBack, _
  ByVal gsdll_stdout As StdIOCallBack, _
  ByVal gsdll_stderr As StdIOCallBack) As Integer

Private Declare Function gsapi_init_with_args Lib "gsdll32.dll" _
  (ByVal instance As IntPtr, _
  ByVal argc As Integer, _
  <MarshalAs(UnmanagedType.LPArray, ArraySubType:=UnmanagedType.LPStr)> _
  ByVal argv() As String) As Integer

Private Declare Function gsapi_exit Lib "gsdll32.dll" _
  (ByVal instance As IntPtr) As Integer

Private Declare Sub gsapi_delete_instance Lib "gsdll32.dll" _
  (ByVal instance As IntPtr)

'--- Run Ghostscript with specified arguments

Public Function RunGS(ByVal ParamArray Args() As String) As Boolean

    Dim InstanceHndl As IntPtr
    Dim NumArgs As Integer
    Dim StdErrCallback As StdIOCallBack
    Dim StdInCallback As StdIOCallBack
    Dim StdOutCallback As StdIOCallBack

    NumArgs = Args.Count

    StdInCallback = AddressOf InOutErrCallBack
    StdOutCallback = AddressOf InOutErrCallBack
    StdErrCallback = AddressOf InOutErrCallBack

    '--- Shift arguments to begin at index 1 (Ghostscript requirement)

    ReDim Preserve Args(NumArgs)
    System.Array.Copy(Args, 0, Args, 1, NumArgs)

    '--- Start a new Ghostscript instance

    If gsapi_new_instance(InstanceHndl, 0) <> 0 Then
        Return False
        Exit Function
    End If

    '--- Set up dummy callbacks

    gsapi_set_stdio(InstanceHndl, StdInCallback, StdOutCallback, StdErrCallback)

    '--- Run Ghostscript using specified arguments

    gsapi_init_with_args(InstanceHndl, NumArgs + 1, Args)

    '--- Exit Ghostscript

    gsapi_exit(InstanceHndl)

    '--- Delete instance

    gsapi_delete_instance(InstanceHndl)

    Return True

End Function

'--- Delegate function for callbacks

Private Delegate Function StdIOCallBack(ByVal handle As IntPtr, _
  ByVal Strz As IntPtr, ByVal Bytes As Integer) As Integer

'--- Dummy callback for standard input, standard output, and errors

Private Function InOutErrCallBack(ByVal handle As IntPtr, _
  ByVal Strz As IntPtr, ByVal Bytes As Integer) As Integer

    Dim objString As String
    objString = Marshal.PtrToStringAnsi(Strz, Bytes)       
    Return 0

End Function

关于如何避免这种情况的任何想法?我不介意采取快速流程或其他方式。正如我所说,这只发生在某些特定文件上(我们从客户那里获得),但可能其中 98% 的文件大小都正确减小了。

好的,所以你说“它不会提示任何错误”,但是当我 运行 你的文件在这里 Ghostscript 开始时说:

**** Warning: Discovered more entries in xref than declared in trailer /Size
   **** Warning:  File has an invalid xref entry:  2.  Rebuilding xref table.

然后在每一页上都写着:

   **** Error: stream operator isn't terminated by valid EOL.
               Output may be incorrect.
   **** Error: stream operator isn't terminated by valid EOL.
               Output may be incorrect.

最后是:

   **** This file had errors that were repaired or ignored.
   **** The file was produced by:
   **** >>>>  <<<<
   **** Please notify the author of the software that produced this
   **** file that it does not conform to Adobe's published PDF
   **** specification.

   **** The rendered output from this file may be incorrect.

我会说这是相当多的错误。请注意,当您从 Acrobat 保存文件时,它自然会修复这些语法问题,因此 Ghostscript 当然不会抱怨,因为保存的文件是有效的。

也就是说,使用基于您的命令行:

"c:\program files\gs\gs9.27\bin\gswin64c" -sDEVICE=pdfwrite -sOutputFile=out.pdf -dBATCH -dNOPAUSE -dNOGC -dPDFSETTINGS=/ebook 20194114_EXPORT_DOCS_Original.pdf

产生较少的警告,因为您指定了 -dQUIET。如果您正在尝试调查问题,那么抑制警告可能并不理想。您是否看到 Ghostscript 的任何反向通道输出?如果是这样,你也应该 post 它在这里。如果没有,那么你需要实现代码来捕获它,它的重要信息。

注意不要使用 -dNOGC 这是一个仅用于调试的开关。我知道,人们将其 post 作为他们命令行的一部分,通常是因为他们 'researched it'(在 Google 上找到它)。不要使用它。

无论如何,使用该命令行我得到了一个 PDF 文件,它看起来合理并且是原始文件大小的 20%。

使用您的命令行(或尽可能接近它的东西)不会为我重现问题(在 32 位或 64 位上,使用当前代码或 9.27 版本)所以我可以只推测问题。如果您设置了 -dPDFSTOPONERROR ,它将在读取文件时立即退出(带有冗长的错误消息),并会生成一个空的 PDF 文件。我想不出任何其他方式,尤其是 'with no error'.

FWIW 默认情况下 Ghostscript 尝试修复无效的 PDF 文件,或者至少尽可能忽略错误。 PDFSTOPONERROR 开关旨在用于商业环境,其中重要的是 可能 无法正确呈现的文件被标记并 checked/rejected/repaired 而不是被浪费地打印。

在哪个音符上;我注意到您似乎在商业上使用 Ghostscript,并且正在链接到 DLL。我觉得我应该向您指出提供 Ghostscript 的许可证 (AGPL v3),您可能应该检查您的使用是否符合该许可证的条款。