AWS Lambda函数 - 将PDF转换为图像

时间:2016-08-29 11:20:40

标签: node.js imagemagick ghostscript aws-lambda

我正在开发应用程序,用户可以上传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 convert:%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。 ] killed:false,代码:1,   signal:null,cmd:' / bin / sh -c convert /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...
        }
    });
});

3 个答案:

答案 0 :(得分:4)

您可以在以下存储库中找到Ghostscript for Lambda的编译版本。 您应该将文件添加到要作为源代码上载到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文件。

答案 1 :(得分:0)

使用较旧版本的Ghostscript几乎肯定是一个错误,或者可能是限制。

许多PDF制作人创建的PDF文件不符合规范,但在Adobe Acrobat中无需投诉即可打开。 Ghostscript也努力做到这一点,但显然我们无法知道Acrobat会允许什么,所以我们不断追逐这个模糊的目标。 (FWIW警告是合法的不符合规范的PDF文件)。

除了替换旧版本之外,您无法使用旧版本。

是的,您可以从源代码构建Ghostscript,我不知道nodejs模块,不知道为什么相关。

还有许多其他应用程序将呈现PDF文件,MuPDF是我所知道的另一个。当然,您可以直接使用Ghostscript而无需使用ImageMagick。当然,如果你可以加载另一个应用程序,那么你应该只需要替换你的Ghostscript安装。

答案 2 :(得分:0)

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

https://github.com/rcastoro/PDFImagine

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