【问题标题】:AWS Lambda function - convert PDF to ImageAWS Lambda 函数 - 将 PDF 转换为图像
【发布时间】:2017-01-05 09:54:46
【问题描述】:

我正在开发应用程序,用户可以在其中上传一些 pdf 格式的图纸。上传的文件存储在 S3 上。上传后,文件必须转换为图像。为此,我创建了 lambda 函数,它将文件从 S3 下载到 lambda 执行环境中的 /tmp 文件夹,然后我从 imagemagick 调用“convert”命令。

convert sourceFile.pdf targetFile.png

Lambda 运行环境是 nodejs 4.3。内存设置为 128MB,超时 30 秒。

现在的问题是一些文件转换成功,而另一些文件则失败并出现以下错误:

{ [错误:命令失败:/bin/sh -c convert /tmp/sourceFile.pdf /tmp/targetFile.png 转换:%s' (%d) "gs" -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 "-sDEVICE=pngalpha" -dTextAlphaBits=4 -dGraphicsAlphaBits=4 "-r72x72" "-sOutputFile=/tmp/magick-QRH6nVLV--0000001" "-f/tmp/magick-B610L5uo" "-f/tmp/magick-tIe1MjeR" @ error/utility.c/SystemCommand/1890. convert: Postscript delegate failed/tmp/sourceFile.pdf':没有 文件或目录@error/pdf.c/ReadPDFImage/678。转换:没有图像 定义了`/tmp/targetFile.png' @ 错误/convert.c/ConvertImageCommand/3046。 ] 被杀:假,代码:1, 信号:空,cmd:'/bin/sh -c 转换/tmp/sourceFile.pdf /tmp/targetFile.png' }

起初我不明白为什么会发生这种情况,然后我尝试在本地 Ubuntu 机器上使用相同的命令转换有问题的文件。这是终端的输出:

**** Warning: considering '0000000000 XXXXX n' as a free entry. **** This file had errors that were repaired or ignored. **** The file was produced by: **** >>>> Mac OS X 10.10.5 Quartz PDFContext <<<< **** Please notify the author of the software that produced this **** file that it does not conform to Adobe's published PDF **** specification.

所以消息很清楚,但文件还是会转换为 png。如果我尝试执行convert source.pdf target.pdf 并在此之后执行convert target.pdf image.png,则会修复并转换文件而不会出现任何错误。这不适用于 lambda。

由于同样的事情在一个环境中有效,但在另一个环境中无效,我最好的猜测是 Ghostscript 的版本是问题所在。 AMI 上安装的版本是 8.70。在我的本地机器上,Ghostsript 版本是 9.18。

我的问题是:

  • 是ghostscript的版本问题吗?这是旧版的错误吗 版本的ghostscript?如果没有,我怎么能告诉ghostscript(用或 不使用 imagemagick)来修复或忽略错误,就像它在 我的本地环境?
  • 如果旧版本有问题,是否可以构建ghostscript 从源代码创建 nodejs 模块,然后使用该版本的 ghostscript 而不是安装的那个?
  • 有没有更简单的方法将 pdf 转换为图像而不使用 imagemagick 和 ghostscript?

更新 lambda 代码的相关部分:

var exec = require('child_process').exec;
var AWS = require('aws-sdk');
var fs = require('fs');
...

var localSourceFile = '/tmp/sourceFile.pdf';
var localTargetFile = '/tmp/targetFile.png';

var writeStream = fs.createWriteStream(localSourceFile);
writeStream.write(body);
writeStream.end();

writeStream.on('error', function (err) {
    console.log("Error writing data from s3 to tmp folder.");
    context.fail(err);
});

writeStream.on('finish', function () {
    var cmd = 'convert ' + localSourceFile + ' ' + localTargetFile;

    exec(cmd, function (err, stdout, stderr ) {

        if (err) {
            console.log("Error executing convert command.");
            context.fail(err);
        }

        if (stderr) {
            console.log("Command executed successfully but returned error.");
            context.fail(stderr);
        }else{
            //file converted successfully - do something...
        }
    });
});

【问题讨论】:

  • 您可以添加您的lambda 代码吗?
  • @johni 代码很多,我复制了相关部分。需要帮助请叫我。谢谢

标签: node.js imagemagick ghostscript aws-lambda


【解决方案1】:

您可以在以下存储库中找到适用于 Lambda 的 Ghostscript 的编译版本。 您应该将文件添加到您要作为源代码上传到 AWS Lambda 的 zip 文件中。

https://github.com/sina-masnadi/lambda-ghostscript

这是一个调用 Ghostscript 函数的 npm 包:

https://github.com/sina-masnadi/node-gs

将编译好的 Ghostscript 文件复制到你的项目并添加 npm 包后,你可以使用executablePath('path to ghostscript') 函数将包指向你之前添加的编译好的 Ghostscript 文件。

【讨论】:

  • 您好新浪,谢谢您的回答。这实际上非常有用,但我很久以前就做了一些解决方法来解决我的问题。我会试一试,让你知道它是如何工作的。然而,正如@KenS 所指出的,如果目标 lambda 函数的源代码不是开源的,这种分发可能不符合免费的 Ghostscript 许可证。 artifex.com/licensing
  • @A.Z.感谢您对许可的评论!你知道任何不需要许可的库吗?
  • @A.Z.你能解释一下你为这个问题找到了什么解决方法吗?我们现在面临同样的问题。
  • 使用这个包,我遇到了超时问题。它继续尝试在最后运行命令 CloudWatch 日志显示超时错误。
  • @SinaMasnadi 有什么帮助吗?如果将整体写入单个 .option() 函数,我会遇到超时问题。如果我在单独的函数中编写每个选项,那么它会在日志中给出以下错误2019-08-06T09:40:45.192Z 6a66a9e2-3d6e-4812-8bb8-fa8ecfc630cd stdout: GPL Ghostscript 9.20 (2016-09-26) Copyright (C) 2016 Artifex Software, Inc. All rights reserved. This software comes with NO WARRANTY: see the file PUBLIC for details. Error: /undefinedfilename in (| grep "Page" | wc -l 2&gt;/dev/null)
【解决方案2】:

这几乎可以肯定是旧版 Ghostscript 的错误,或者可能是限制。

许多 PDF 制作者创建的 PDF 文件不符合规范,但在 Adob​​e Acrobat 中打开时会毫无问题。 Ghostscript 也在努力做同样的事情,但显然我们不知道 Acrobat 会允许什么,所以我们一直在追逐这个模糊的目标。 (FWIW 警告是合法的不合规格 PDF 文件)。

除了替换旧版本之外,您无能为力。

是的,你可以从源代码构建 Ghostscript,我不知道 nodejs 模块,不知道为什么会这样。

还有许多其他可以渲染 PDF 文件的应用程序,MuPDF 是我所知道的另一个应用程序。而且,当然,您可以不使用 ImageMagick 直接使用 Ghostscript。当然,如果您可以加载另一个应用程序,那么您应该也可以替换您的 Ghostscript 安装。

【讨论】:

  • 非常感谢肯的回答。不幸的是,我无法替换 GS 安装。这特别是 AWS 的事情。您只能执行代码并使用预安装的包。您必须使用应用程序部署的所有其他内容,包括 npm 模块。我可能可以创建 EC2 实例并安装我需要的版本,但我猜只使用它来转换 pdf 文件是一种矫枉过正的做法。从源代码和节点模块构建是相关的,因为我可以使用我的代码部署编译的库并使用它而不是安装一个。
  • 请注意 Ghostscript 已获得 AGPL 许可。如果您将 Ghostscript 构建到应用程序中,则需要确保您遵守许可协议。
  • 感谢您注意到这一点。如果我必须在我的 lambda 函数中包含特定版本的 GS,那么获得商业许可证将不是问题。
  • 我们通过改用 GraphicsMagic 解决了 ImageMagick 中的一些问题,Node.js 中的“gm”模块可以使用它。我们必须在 Amazon Linux 上自行编译以进行部署。但是您可以先在本地尝试一下,看看它是否适用于您的 PDF。只是提供了另一种可能的途径。
  • @ToddPrice 感谢您的贡献,您的评论指出了应该如何完成。事情是'gm'节点模块仍在使用ghostscript。我认为pdf文件的问题与“gm”节点模块有关,这就是我选择自己生成转换命令的原因。我当然错了。你是用你的节点模块编译ghostscript,还是你只是用你的代码交付节点模块(在这种特殊情况下是'gs')并使用现有的ghostscript安装?
【解决方案3】:

aws 上的 GS 版本是具有已知错误的旧版本。我们可以通过上传一个专门为 Linux 编译的 x64 GS 文件来解决这个问题。然后使用新的 AWS lambda 层上传。我在这里编写了一个节点函数:

https://github.com/rcastoro/PDFImagine

但是,请确保您的 lambda 具有该 GS 层!

【讨论】:

    猜你喜欢
    • 2019-01-08
    • 1970-01-01
    • 2019-10-20
    • 2020-08-27
    • 2020-03-01
    • 2022-01-28
    • 2017-03-19
    • 2021-04-23
    • 1970-01-01
    相关资源
    最近更新 更多