【问题标题】:Ghostscript.NET Rasterizer Out of MemoryGhostscript.NET 光栅化程序内存不足
【发布时间】:2015-11-03 20:49:39
【问题描述】:

我正在使用Ghostscript.NET,这是一个方便的用于 Ghostscript 功能的 C# 包装器。我有一批从客户端发送的 PDF 文件被转换为 ASP .NET WebAPI 服务器上的图像并返回给客户端。

public static IEnumerable<Image> PdfToImagesGhostscript(byte[] binaryPdfData, int dpi)
{
    List<Image> pagesAsImages = new List<Image>();

    GhostscriptVersionInfo gvi = new GhostscriptVersionInfo(AppDomain.CurrentDomain.BaseDirectory + @"\bin\gsdll32.dll");

    using (var pdfDataStream = new MemoryStream(binaryPdfData))
    using (var rasterizer = new Ghostscript.NET.Rasterizer.GhostscriptRasterizer())
    {
        rasterizer.Open(pdfDataStream, gvi, true);

        for (int i = 1; i <= rasterizer.PageCount; i++)
        {
            Image pageAsImage = rasterizer.GetPage(dpi, dpi, i); // Out of Memory Exception on this line
            pagesAsImages.Add(pageAsImage);
        }
    }
    return pagesAsImages;
}

这通常可以正常工作(我通常使用 500 dpi,我知道这很高,但即使降至 300 我也可以重现此错误)。但是,如果我从客户端提供许多 PDF(例如 150 个 1 页 PDF),它通常会在 Ghostscript.NET Rasterizer 中遇到内存不足异常。我该如何克服呢?这应该穿线吗?如果是这样,那将如何工作?使用 64 位版本的 GhostScript 会有帮助吗?提前致谢。

【问题讨论】:

  • 您可以在pageAsImage 上拨打DisposeAdd 之后吗?不,线程不会帮助解决这个内存问题。是的,在 64 位进程中运行可能会有所帮助。如果这些都没有帮助,那么可能需要显式调用 GC.Collect()(尽管这确实是一个糟糕的 hack)。
  • @ChrisO 谢谢,但处理它会使其在返回的对象中无法访问。尝试使用 64 位 dll 时出现此错误“您正在使用在 32 位进程中为 64 位系统编译的本机 Ghostscript 库 (gsdll64.dll)。您需要使用 gsdll32.dll。”知道为什么它是 32 位进程吗?我正在通过 Visual Studio 2015 中的调试运行 ASP .NET WebAPI。
  • Tools | Options | Projects and Solutions | Web Projects | Use the 64 bit version of IIS Express 但我自己没有用 VS2015 尝试过。
  • 自从切换到64位后,我没有遇到内存不足的异常。
  • 太棒了,很高兴听到它。

标签: c# asp.net out-of-memory ghostscript ghostscript.net


【解决方案1】:

我自己是新手,在这里寻找技巧。

根据文档here 中的示例,它们显示如下:

for (int page = 1; page <= _rasterizer.PageCount; page++)
{
    var docName = String.Format("Page-{0}.pdf", page);
    var pageFilePath = Path.Combine(outputPath, docName);
    var pdf = _rasterizer.GetPage(desired_x_dpi, desired_y_dpi, pageNumber);
    pdf.Save(pageFilePath);
    pagesAsImages.Add(pdf);
}

您似乎没有保存文件。

我仍在努力让类似的东西也能在我的身上发挥作用。目前,我将尝试两种方法,首先使用 GhostscriptProcessor

private static void GhostscriptNetProcess(String fileName, String outputPath)
{
    var version = Ghostscript.NET.GhostscriptVersionInfo.GetLastInstalledVersion();
    var source = (fileName.IndexOf(' ') == -1) ? fileName : String.Format("\"{0}\"", fileName);
    var gsArgs = new List<String>();
    gsArgs.Add("-q");
    gsArgs.Add("-dNOPAUSE");
    gsArgs.Add("-dNOPROMPT");
    gsArgs.Add("-sDEVICE=pdfwrite");
    gsArgs.Add(String.Format(@"-sOutputFile={0}", outputPath));
    gsArgs.Add(source);
    var processor = new Ghostscript.NET.Processor.GhostscriptProcessor(version, false);
    processor.Process(gsArgs.ToArray());
}

下面的这个版本和你的相似,在我开始寻找其他代码示例之前我开始使用的版本:

private static void GhostscriptNetRaster(String fileName, String outputPath)
{
    var version = Ghostscript.NET.GhostscriptVersionInfo.GetLastInstalledVersion();
    using (var rasterizer = new Ghostscript.NET.Rasterizer.GhostscriptRasterizer())
    {
        rasterizer.Open(File.Open(fileName, FileMode.Open, FileAccess.Read), version, false);
        for (int page = 0; page < rasterizer.PageCount; page++)
        {
            var img = rasterizer.GetPage(96, 96, page);
            img.Save(outputPath);
        }
    }
}

这能带你到任何地方吗?

【讨论】:

  • 我正在尝试从 pdf 文档中获取特定页面,第一次没问题,但是当我尝试从该 pdf 文档中转换另一个页面时,out of memory 错误阻止我。我试图解决它已经两天了,我几乎尝试了所有解决方案,但还没有运气。任何帮助将不胜感激。
  • @metmirr - 那是一份合同工作,我不再拥有它的代码。我工作过的最好的代码段发布在这里:stackoverflow.com/a/34770558/153923
  • 如果您有一台 32 位 PC 或您的程序正在使用 32 位插件,您将能够访问的最大文件大小为 2GB。
【解决方案2】:

您不必在同一个 GhostscriptRasterizer 实例中对所有页面进行光栅化。在每个页面上使用一次性光栅器并在 List Image 或 List byte[] 中收集结果。 结果示例 Jpeg 编码字节数组列表。

List<byte[]> result = new List<byte[]>();

for (int i = 1; i <= pdfPagesCount; i++)
{
    using (var pageRasterizer = new GhostscriptRasterizer())
    {
        pageRasterizer.Open(stream, gsVersion, true);

        using (Image tempImage = pageRasterizer.GetPage(dpiX, dpiY, i))
        {
            var encoder = ImageCodecInfo.GetImageEncoders().First(c => c.FormatID == System.Drawing.Imaging.ImageFormat.Jpeg.Guid);
            var encoderParams = new EncoderParameters() { Param = new[] { new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 95L) } };

            using (MemoryStream memoryStream = new MemoryStream())
            {
                tempImage.Save(memoryStream, encoder, encoderParams);
                result.Add(memoryStream.ToArray());
            }
        }
    }
}

如果您不知道 PDF 的页数,您可以调用 rasterizer 一次,并获取 PageCount 属性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-23
    • 2015-12-14
    • 2014-02-18
    • 1970-01-01
    相关资源
    最近更新 更多