ImageMagick 不再在 AWS Lambda 中转换 pdf

ImageMagick not converting pdfs anymore in AWS Lambda

在过去的 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);
  })
});

错误响应:

std error dataconvert: unable to load module `/usr/lib64/ImageMagick-6.7.8/modules-Q16/coders/pdf.la': file not found

我也尝试过移动到 Node.js 10.x 并使用可通过 aws 无服务器应用程序存储库获得的 ImageMagick 层。在同一代码上尝试此操作会生成此错误

std error data convert: 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 文件的最佳方法是什么?

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

程序在 upcoming-updates-to-the-aws-lambda-execution-environment

中有描述

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

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

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

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

我遇到了不再找到 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")

虽然其他答案有所帮助,但要找到可行的解决方案还有很多工作要做,所以下面是我设法解决这个问题的方法,特别是针对 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 中创建一个新函数,Select 浏览无服务器应用程序存储库,搜索 "ImageMagick" 和 select "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 库时遇到了问题。如果有更好的方法告诉我。

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