【问题标题】:ImageMagick not converting pdfs anymore in AWS LambdaImageMagick 不再在 AWS Lambda 中转换 pdf
【发布时间】:2019-11-25 18:51:38
【问题描述】:

在过去的 18 个月里,我在 S3 对象上运行了一个 AWS Lambda 函数,但它在大约一个月前在一次小更新后就死了。我已经恢复了它,但它仍然坏了。我已经研究过使用 ImageMagick 进行最基本的 pdf 转换,但没有成功,所以我认为 AWS 更新了一些内容并导致 pdf 模块被删除或停止工作。

我只完成了我在 Node.js 8.10 中的核心代码中基本完成的基本功能:

gm(response.Body).setFormat("png").stream((err, stdout,stderr) => {
  if (err) {
    console.log('broken');
  }
  const chunks = [];
  stdout.on('data', (chunk) => {
    chunks.push(chunk);
  });
  stdout.on('end', () => {
    console.log('gm done!');
  });
  stderr.on('data', (data) => {
    console.log('std error data ' + data);
  })
});

带有错误响应:

标准错误数据转换:无法加载模块`/usr/lib64/ImageMagick-6.7.8/modules-Q16/coders/pdf.la':找不到文件

我还尝试迁移到 Node.js 10.x 并使用可通过 aws 无服务器应用程序存储库获得的 ImageMagick 层。在相同的代码上尝试这个会产生这个错误

标准错误数据转换:FailedToExecuteCommand `'gs' -sstdout=%stderr -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 '-sDEVICE=pngalpha' -dTextAlphaBits=4 -dGraphicsAlphaBits=4 '-r72x72' '-sOutputFile=/tmp/magick-22TOeBgB4WrfoN%d' '-f/tmp/magick-22KvuEBeuJuyq3' '-f/tmp/magick-22dj24vSktMXsj'' (1) @error/pdf。 c/InvokePDFDelegate/292

在这两种情况下,该函数在图像文件上运行时都能正常工作。

基于此,我认为 aws 8.10 ImageMagick 和 10 层都缺少 pdf 模块,但我不确定如何添加它或为什么首先将其删除。修复此功能的最佳方法是什么?

编辑

所以我已经下载了https://github.com/serverlesspub/imagemagick-aws-lambda-2 并手动构建了库,将其上传到 Lambda 并使其成功地作为一个层工作,但是它不包含作为可选库的 GhostScript。我尝试将它添加到Makefile_ImageMagick,它构建并在结果中有一些对 Ghostscript 的引用,但运行它并不能解决 PDF 问题(图像仍然有效)。将 GhostScript 可选库添加到 Make 文件的最佳方法是什么?

【问题讨论】:

  • 您是否为 Imagemagick 安装了 Ghostscript?如果你不这样做,那么你需要它。如果您这样做,那么您可能需要编辑 delegates.xml 文件以插入到 gs (ghostscript) 的完整路径以获取 PDF 相关条目。或者您可能需要编辑您的 policy.xml 文件以授予对 PDF 文件的读写权限。见stackoverflow.com/questions/52861946/…。对不起,我不知道或使用 AWS
  • @fmw42 我不需要,但我以前不需要它。 AWS 是否删除了它?
  • 什么意思,你以前不需要它?在 AWS 或只是 Imagemagick 上。阅读 PDF 文件总是需要 Ghostscript。不需要编写它们。如果您的 Imagemagick 版本以前是旧的,则 policy.xml 文件可能没有包含它。它是在几个月前报告有关 Ghostscript 的安全错误时添加的。也许 AWS 更新了 Imagemagick 并在 policy.xml 文件中引入了新条目。或者他们可能遗漏了 Ghostscript。
  • 同样的问题!看起来像一个 AWS 问题,因为它已经运行了一年多...
  • 我相信AWS Lambda默认不再包含ghostscript,也就是ImageMagick使用的PDF委托。

标签: node.js amazon-web-services pdf aws-lambda imagemagick


【解决方案1】:

虽然其他答案有所帮助,但要找到一个可行的解决方案还有很多工作要做,所以下面是我设法解决这个问题的方法,特别是针对 NodeJS。

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

压缩 bin 目录并将其作为层上传到 Lambda。

https://github.com/sina-masnadi/node-gs 添加到您的 NodeJS 模块中。您可以将它们作为项目的一部分上传,也可以按照我的方式上传(以及所有其他必需的)。

https://github.com/serverlesspub/imagemagick-aws-lambda-2 添加为图层。最好的方法是在 Lambda 中创建一个新函数,选择浏览无服务器应用程序存储库,搜索“ImageMagick”并选择“image-magick-lambda-layer”(您也可以构建它并将其上传为层) .

将三层添加到你的函数中,我已经按照这个顺序完成了

  1. GhostScript
  2. ImageMagick
  3. NodeJS 模块

将 appPath 添加到 ImageMagick 和 GhostScript 的 require 语句中:

var gm = require("gm").subClass({imageMagick: true, appPath: '/opt/bin/'});
var gs = require('gs');

我的是在一个异步瀑布中,所以在我之前的处理函数之前,我添加了这个函数来转换为 png,如果不是图像的话:

  function convertIfPdf(response, next) {
    if (fileType == "pdf") {
      fs.writeFile("/tmp/temp.pdf", response.Body, function(err) {
        if (!err) {
          gs().batch().nopause().executablePath('/opt/bin/./gs').device('png16m').input("/tmp/temp.pdf").output('/tmp/temp.png').exec(function (err, stdout, stderr){
            if (!err && !stderr) {
              var data = fs.readFileSync('/tmp/temp.png');
              next(null, data);
            } else {
              console.log(err);
              console.log(stderr);
            }
          });
        }
      });
    } else {
      next(null, response.Body);
    }
  }

从那时起,您可以执行之前在 ImageMagick 中执行的操作,因为它的格式相同。可能有更好的方法来进行 pdf 转换,但除非使用文件,否则我遇到了 GS 库的问题。如果有更好的方法请告诉我。

如果您在加载库时遇到问题,请确保路径正确,这取决于您如何压缩它。

【讨论】:

  • @SachinChavan 这是完全相同的结果,除了这个答案有更清晰的步骤并使用层进行良好的重用。它甚至在博文中说它做了同样的事情。
  • 你是对的,我正在尝试这个但无法跟随图层的东西,这真的很好。我已经在 zip 中添加了这些二进制文件并上传了它。会试一试。谢谢你,它真的很有用。
  • 如果假设我想拍摄图像并上传到 S3,我们如何使用 GS 来做到这一点?@Rudiger,如果你输出到 /tmp/temp.png,不会写到本地lambda的文件系统?那将被保存在哪里?因为 lambda 是无状态的,是的(lambda 与 EC2 有文件系统的 EC2 不同)?
  • @KJAng 是的,您需要编写代码来拾取并移动它,但这超出了此答案的范围。有许多教程会向您展示执行此操作的代码,这个答案是特定于它的 GS 部分的。
  • @Rudiger,感谢您的回答。还有一个问题。你为什么要var data = fs.readFileSync('/tmp/temp.png');?是因为您要使用数据发送到 S3 吗?数据是缓冲区还是 base64 或其他?
【解决方案2】:

我遇到了同样的问题。由于 pdf.la not found 错误,每天处理数千个 PDF 页面的两个云服务失败。

解决方案是从 Image Magick 切换到 GhostScript 以将 PDF 转换为 PNG,然后将 ImageMagick 与 PNG 结合使用(如果需要)。这样,IM 永远不必处理 PDF,也不需要 pdf.la 文件。

要在 AWS Lambda 上使用 GhostScript,只需将 gs 二进制文件上传到函数 zip 文件中。

【讨论】:

  • 这太糟糕了。一旦我调查了它,我会试一试并更新它。你刚刚构建了github.com/sina-masnadi/lambda-ghostscript吗?
  • @Rudiger 我在 Amazon Linux EC2 实例上安装了 ghostscript,使用“whereis”查找“gs”二进制文件,使用“lld gs”获取所需库的列表。将 gs 二进制文件添加到函数 zip 文件的根目录中,并将库添加到函数 zip 文件内的“lib”文件夹中。
  • @Rudiger 另外,更改了 lambda 函数代码,以便它可以在 /var/task/gs 中找到 gs 二进制文件。
  • 谢谢,我已将 ImageMagick 添加为一个效果很好的图层,因此我也会将 gs 添加为一个图层。
  • 虽然这不是我的答案,但它对我得到的答案最有帮助,所以我会奖励它。
【解决方案3】:

您可以向您的 lambda 函数添​​加一个层,以使其在 2019 年 7 月 22 日之前再次工作。 您需要添加的层的 ARN 如下:arn:aws:lambda:::awslayer:AmazonLinux1703

该过程在upcoming-updates-to-the-aws-lambda-execution-environment进行了描述

任何长期的解决方案都会很棒。

【讨论】:

  • 谢谢。它确实解决了这个问题,但只有 2 天,这不是很好。由于这个原因,可能无法将其标记为正确,但现在绝对是临时修复。
【解决方案4】:

我遇到了找不到 ghostscript 的问题。

以前,我通过以下方式引用了 ghostscript:

var gs = '/usr/bin/gs';

由于 AWS lambda 停止提供该软件包,我将其直接包含在我的 lambda 函数中,该函数对我有用。我刚刚从https://github.com/sina-masnadi/lambda-ghostscript 下载了文件并将其放在一个名为“ghostscript”的文件夹中,然后这样引用它:

var path = require('path')
var gs = path.join(__dirname,"ghostscript","bin","gs")

【讨论】:

    猜你喜欢
    • 2020-08-27
    • 2016-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-05
    • 2015-09-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多