title: AWS Lambda function - convert PDF to Image
body: <p>I am developing application where user can upload some drawings in pdf format. Uploaded files are stored on S3. After uploading, files has to be converted to images. For this purpose I have created lambda function which downloads file from S3 to /tmp folder in lambda execution environment and then I call ‘convert’ command from imagemagick. </p>
  
  <p><code>convert sourceFile.pdf targetFile.png</code></p>
  
  <p>Lambda runtime environment is nodejs 4.3. Memory is set to 128MB, timeout 30 sec.</p>
  
  <p>Now the problem is that some files are converted successfully while others are failing with the following error: </p>
  
  <blockquote>
    <p>{ [Error: Command failed: /bin/sh -c convert /tmp/sourceFile.pdf
    /tmp/targetFile.png convert: <code>%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</code>/tmp/sourceFile.pdf': No such
    file or directory @ error/pdf.c/ReadPDFImage/678. convert: no images
    defined `/tmp/targetFile.png' @
    error/convert.c/ConvertImageCommand/3046. ] killed: false, code: 1,
    signal: null, cmd: '/bin/sh -c convert /tmp/sourceFile.pdf
    /tmp/targetFile.png' }</p>
  </blockquote>
  
  <p>At first I did not understand why this happens, then I tried to convert problematic files on my local Ubuntu machine with the same command. This is the output from terminal: </p>
  
  <p><code>**** Warning: considering '0000000000 XXXXX n' as a free entry.
     **** This file had errors that were repaired or ignored.
     **** The file was produced by: 
     **** &gt;&gt;&gt;&gt; Mac OS X 10.10.5 Quartz PDFContext &lt;&lt;&lt;&lt;
     **** Please notify the author of the software that produced this
     **** file that it does not conform to Adobe's published PDF
     **** specification.</code></p>
  
  <p>So the message was very clear, but the file gets converted to png anyway. If I try to do <code>convert source.pdf target.pdf</code> and after that <code>convert target.pdf image.png</code>, file is repaired and converted without any errors. This doesn’t work with lambda. </p>
  
  <p>Since the same thing works on one environment but not on the other, my best guess is that the version of Ghostscript is the problem. Installed version on AMI is 8.70. On my local machine Ghostsript version is 9.18.</p>
  
  <p>My questions are: </p>
  
  <ul>
  <li>Is the version of ghostscript problem? Is this a bug with older
  version of ghostscript? If not, how can I tell ghostscript (with or
  without using imagemagick) to repair or ignore errors like it does on
  my local environment?</li>
  <li>If the old version is a problem, is it possible to build ghostscript
  from source, create nodejs module and then use that version of
  ghostscript instead the one that is installed?</li>
  <li>Is there an easier way to convert pdf to image without using
  imagemagick and ghostscript?</li>
  </ul>
  
  <p><strong>UPDATE</strong>
  Relevant part of lambda code: </p>
  
  <pre><code>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...
          }
      });
  });
  </code></pre>