Convert office files to pdf using Lambda

0

I'm currently creating an AWS Lambda function to convert office files to pdf using LibreOffice in a Lambda Layer.

So I have used code from a developer and I'm trying to make it work but every time I try something else I get another error, this time I feel I'm close to success but the following error keeps appearing when I test the function:

"errorType": "TypeError", "errorMessage": "Cannot read properties of undefined (reading '0')", "trace": [ "TypeError: Cannot read properties of undefined (reading '0')", " at Runtime.module.exports.handler (/var/task/index/index.js:36:23)", " at runMicrotasks ()", " at processTicksAndRejections (node:internal/process/task_queues:96:5)"

The original post I'm following is at the below link:

https://madhavpalshikar.medium.com/converting-office-docs-to-pdf-with-aws-lambda-372c5ac918f1

The code I'm using is below:

const https = require('https');
const path = require('path');
const fs = require('fs');
var async = require('async');
const {writeFileSync} = require('fs');
const lambdafs = require('lambdafs');
const {execSync} = require('child_process');
var AWS = require('aws-sdk');

const inputPath = path.join( '/opt', 'lo.tar.br'); 
const outputPath = '/tmp/';
const bucketName = 'doc-conversion-tests';

module.exports.handler = async (event, context) => {
  console.log(execSync('ls -alh /opt').toString('utf8'));

  try {
    // Decompressing
    let decompressed = {
      file: await lambdafs.inflate(inputPath)
    };

    console.log('output brotli de:----', decompressed); 
  } catch (error) {
    console.log('Error brotli de:----', error);
  }

  try {
    console.log(execSync('ls -alh /opt').toString('utf8')); 
  } catch (e) {
    console.log(e);
  }

  var body = "";
  //S3 put event
  body = event.Records[0].body;
  console.log('s3 bucket file name from event:', body);

  // get file from s3 bucket
  var s3fileName = body;
  var newFileName = Date.now()+'.pdf';
  var s3 = new AWS.S3({apiVersion: '2006-03-01'});
  var fileStream = fs.createWriteStream('/tmp/'+s3fileName);

  var getObject = function(keyFile) {
      return new Promise(function(success, reject) {
          s3.getObject(
              { Bucket: bucketName, Key: keyFile },
              function (error, data) {
                  if(error) {
                      reject(error);
                  } else {
                      success(data);
                  }
              }
          );
      });
  }

  let fileData = await getObject(s3fileName);
    try{  
      fs.writeFileSync('/tmp/'+s3fileName, fileData.Body);
    } catch(err) {
      // An error occurred
      console.error('file write:', err);
    }

    const convertCommand = `export HOME=/tmp && /tmp/lo/instdir/program/soffice.bin --headless -    - 
 norestore --invisible --nodefault --nofirststartwizard --nolockcheck --nologo --convert-to 
"pdf:writer_pdf_Export" --outdir /tmp /tmp/${s3fileName}`;
    try {
      console.log(execSync(convertCommand).toString('utf8'));
    } catch (e) {
      console.log(execSync(convertCommand).toString('utf8'));
    }
    console.log(execSync('ls -alh /tmp').toString('utf8'));

    function uploadFile(buffer, fileName) {
     return new Promise((resolve, reject) => {
      s3.putObject({
       Body: buffer,
       Key: fileName,
       Bucket: bucketName,
      }, (error) => {
       if (error) {
        reject(error);
       } else {

        resolve(fileName);
       }
      });
     });
    }


    let fileParts = s3fileName.substr(0, s3fileName.lastIndexOf(".")) + ".pdf";
    let fileB64data = fs.readFileSync('/tmp/'+fileParts);
    await uploadFile(fileB64data, 'pdf/'+fileParts);
    console.log('new pdf converted and uploaded!!!');
};

Can someone please give me some advise on what is causing the error as I must fix the solution ASAP as I have a deadline to put a solution in place to decom current server solution.

Please help!! - All suggestions welcomed.

Many thanks

I have tried adding a document name (test.doc) instead of a "0" but made no difference, as indicated there is a problem @ line 36 but no idea what to try next.

  • I would like to help you but your code is kind of all over the place. Can you provide more information? Is the file being uploaded a compressed file? Your code would suggest the file being uploaded is always a *.tar.br file type. If this is true, you should download the file first then extract it, convert it and finally upload it. I would recommend that you scale back your script to just console logging the event and then building out your script from there. I can help provide an example if you provide the steps necessary to complete the task as well as help you set up S3 and Lambda correctly.

profile picture
MarkB
asked 10 months ago1002 views
2 Answers
0

Hi, can you use markup to make your code more readable like this?

const https = require('https');
const path = require('path');

From your error message "errorType": "TypeError", "errorMessage": "Cannot read properties of undefined (reading '0')", "trace": [ "TypeError: Cannot read properties of undefined (reading '0')", " at Runtime.module.exports.handler (/var/task/index/index.js:36:23)", " at runMicrotasks ()", " at processTicksAndRejections (node:internal/process/task_queues:96:5)", I can observe that there's a problem in line 36 caused by indexing an undefined object which is supposed to be an array.

profile picture
HS
answered 10 months ago
  • Sorry code is now formatted correctly. This lambda function uses a PUT trigger of a file being uploaded to an S3 bucket which should be used as the file to generate a PDF from

  • Seems like the input event was not set properly. It should have the same structure as presented in this documentation.

    You said the "lambda function uses a PUT trigger of a file being uploaded to an S3 bucket", then did you actually upload a file to S3 bucket and have this function triggered automatically?

    Add a console.log(event) line before body = event.Records[0].body; to check if the Lambda event is propagated correctly. As a general tip for developers, you should utilize logging functionality to inspect the problematic places (in this case, event).

0

When uploading the code it was too large to use the inline code editor and no deploy code button was visible so I assume the code deployed. I received this info message after uploading code:

The deployment package of your Lambda function "DocConversionTest" is too large to enable inline code editing. However, you can still invoke your function.

I tried uploading a file to S3 but nothing seemed to trigger via Lambda function so I manually clicked the test button and thats how I received the error message.

I also tried adding the name of the uploaded file to to the Body = 'filename.ext'; replacing the event.Records[0].body; - this actually worked when I ran via test button, but obviously is not the desired way to trigger.

Tried uploading a file again and it still doesn't seem to trigger the function

profile picture
MarkB
answered 10 months ago
  • When uploading the code it was too large to use the inline code editor and no deploy code button was visible so I assume the code deployed. I received this info message after uploading code:

    The deployment package of your Lambda function "DocConversionTest" is too large to enable inline code editing. However, you can still invoke your function.

    You can export the deployed package from Lambda Console.

    I tried uploading a file to S3 but nothing seemed to trigger via Lambda function Tried uploading a file again and it still doesn't seem to trigger the function

    Which prefix or suffix did you configure for S3 Bucket trigger event? Did you upload your file to the location that matches the S3 prefix and suffix?

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions