You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS Lambda(Node.js)转Office文件为PDF遇TypeError报错求助

问题描述

开发一款基于Lambda Layer中LibreOffice的AWS Lambda(Node.js)函数,用于将Office文件转换为PDF。调试时多次出现不同报错,当前遇到的错误:

"errorType": "TypeError", "errorMessage": "Cannot read properties of undefined (reading '0')"

报错位置在/var/task/index/index.js第36行,对应代码:body = event.Records[0].body;。尝试直接指定文件名(test.doc)但无效,使用的代码如下:

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!!!');
};
错误原因

第36行报错是因为event.Records未定义,说明当前Lambda触发的事件不是S3 Put事件结构:

  • 手动测试时用了默认测试事件,而非正确的S3事件模板;
  • 通过其他方式触发Lambda,事件结构不符合S3上传格式;
  • 直接指定文件名时,未注释掉依赖event.Records的代码,导致代码仍尝试读取不存在的字段。
解决方案

1. 确保触发事件为正确的S3 Put结构

如果通过S3上传触发Lambda,确认S3触发器已正确配置;如果手动测试,使用AWS提供的S3 Put事件模板,示例结构如下:

{
  "Records": [
    {
      "body": "test.doc"
    }
  ]
}

2. 添加事件校验,避免崩溃

在读取event.Records前增加判断,防止因事件格式错误导致函数崩溃:

var body = "";
// 校验事件结构
if (event.Records && event.Records.length > 0) {
  body = event.Records[0].body;
  console.log('s3 bucket file name from event:', body);
} else {
  // 测试时手动指定文件名
  body = "test.doc";
  console.log('Using manual test filename:', body);
}
var s3fileName = body;

3. 手动测试时的正确方式

如果要跳过S3事件直接测试文件转换,直接给s3fileName赋值,并注释掉读取event.Records的代码:

// 注释掉原事件读取代码
// var body = "";
// body = event.Records[0].body;
// console.log('s3 bucket file name from event:', body);

// 手动指定文件名
var s3fileName = "test.doc";

4. 额外检查点

  • 确认Lambda Layer中的lo.tar.br已正确部署,解压路径/tmp/lo存在;
  • 检查S3桶doc-conversion-tests中存在test.doc文件,且Lambda有该桶的读写权限;
  • 转换命令中的LibreOffice路径/tmp/lo/instdir/program/soffice.bin是否正确,可通过ls -alh /tmp/lo/instdir/program确认文件存在。

内容的提问来源于stack exchange,提问作者Nitrox

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 16:18:25