我正在开发应用程序,用户可以上传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。
我的问题是:
更新 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...
}
});
});
答案 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层!