读取 aws lambda 包中的打包文件

Posted

技术标签:

【中文标题】读取 aws lambda 包中的打包文件【英文标题】:reading a packaged file in aws lambda package 【发布时间】:2017-04-25 02:19:59 【问题描述】:

我有一个非常简单的节点 lambda 函数,它读取其中的打包文件的内容。我将代码作为 zip 文件上传。目录结构如下。

index.js
readme.txt

然后在我的 index.js 文件中:

fs.readFile('/var/task/readme.txt', function (err, data) 
if (err) throw err;
);

我不断收到以下错误 NOENT: no such file or directory, open '/var/task/readme.txt'.

我也试过 ./readme.txt。

我错过了什么?

【问题讨论】:

听起来文本文件可能没有包含在您的 zip 中,所以我首先会通过从控制台下载 zip 文件来仔细检查。否则,您介意添加更多上下文吗?你的处理函数的其余部分是什么样的? 实际上我正在使用无服务器框架将 zip 文件打包并上传到 S3。我检查了 S3 文件,它确实包含该文件。我要做的是读取 kms 加密数据密钥,以便我的 lambda 可以从 kms 获取加密密钥,以加密对第 3 方的出站 http 调用。 S3 文件是否在您期望的位置包含 txt 文件?此外,如果 serverless 更改了函数的 cwd,则使用像 './readme.txt' 这样的相对路径可能不起作用。也许尝试 __dirname + '/readme.txt' 或者您可以尝试使用 process.cwd() 记录 lambda 函数的 cwd 【参考方案1】:

试试这个,它对我有用:

'use strict'

let fs = require("fs");
let path = require("path");

exports.handler = (event, context, callback) => 
        // To debug your problem
        console.log(path.resolve("./readme.txt"));

        // Solution is to use absolute path using `__dirname`
        fs.readFile(__dirname +'/readme.txt', function (err, data) 
            if (err) throw err;
        );
;

要调试代码不工作的原因,请在处理程序中添加以下链接

console.log(path.resolve("./readme.txt"));

AWS Lambda 节点进程可能从其他文件夹运行,它会从该文件夹中查找 readme.txt 文件,因为您提供了 relative 路径,解决方案是使用 absolute 路径。

【讨论】:

在使用 Webpack 时使用 __dirname 往往会失败并解析错误的文件夹。在这种情况下,最好使用process.env.LAMBDA_TASK_ROOT,并根据这个环境变量重建真实路径。 @jaym 如果我使用相同的进程,它会向我抛出找不到文件的错误。在无服务器 Lambda 中获取文件的基本路径是什么?【参考方案2】:

这是一个古老的问题,但在尝试整理 Lambda 上的文件路径时首先出现。

无服务器框架的其他步骤

对于使用无服务器框架进行部署的任何人(可能使用 webpack 构建),您还需要将以下内容添加到您的 webpack 配置文件中(紧跟在 target: node 之后):

  // assume target: 'node', is here

  node: 
    __dirname: false,
  ,

如果没有这篇文章,将 __dirname 与 Serverless 一起使用将仍然无法为您提供所需的绝对目录路径。

【讨论】:

如果你使用 webpack 构建,不用再找了。这是你的答案。【参考方案3】:

对我有用的是 Vador 请求使用 process.env.LAMBDA_TASK_ROOT 的 comment。当我在我的机器上使用 __dirname 或在 Lambda 上运行时使用 process.env.LAMBDA_TASK_ROOT 变量在本地运行它时,我编写了一个函数来获取 /templates 目录中的模板文件:

function loadTemplateFile(templateName) 
  const fileName = `./templates/$templateName`
  let resolved
  if (process.env.LAMBDA_TASK_ROOT) 
    resolved = path.resolve(process.env.LAMBDA_TASK_ROOT, fileName)
   else 
    resolved = path.resolve(__dirname, fileName)
  
  console.log(`Loading template at: $resolved`)
  try 
    const data = fs.readFileSync(resolved, 'utf8')
    return data
   catch (error) 
    const message = `Could not load template at: $resolved, error: $JSON.stringify(error, null, 2)`
    console.error(message)
    throw new Error(message)
  

【讨论】:

【参考方案4】:

我使用无服务器框架完成了此操作,它确实是未在压缩中发送的文件。只需在 serverless.yml 中添加以下行:

package:
  individually: false
  include:
    - src/**

【讨论】:

【参考方案5】:

const filepath = path.resolve('../../filename.text');

const fileData2 = fs.readFileSync(process.env.LAMBDA_TASK_ROOT + 文件路径, 'utf-8');

【讨论】:

如果您包含您提供的两个代码行的上下文,这将是一个更好的答案。他们应该去哪里? fileData2 应该如何使用?为什么会这样?【参考方案6】:

我使用的是fs.promises.readFile()。无法让它出错。文件就在那里,我觉得 LAMBDA_TASK_ROOT 也是正确的。改成fs.readFileSync()后,就成功了。

【讨论】:

【参考方案7】:

我遇到了同样的问题,我尝试应用上面所有这些出色的解决方案 - 但没有奏效。

问题是我设置了一个文件夹名称,其中一个字母大写,实际上是小写。 所以当我试图获取 /src/SOthing/some_file.txt 的内容时 虽然该文件夹实际上是 /src/Something/ - 我收到了这个错误...

Windows(本地环境)不区分大小写,而 AWS 不区分大小写!!!....

【讨论】:

以上是关于读取 aws lambda 包中的打包文件的主要内容,如果未能解决你的问题,请参考以下文章

打包部署后无法读取jar包里的文件(实测可行,Java中读取jar包中的文件)

使用 AWS Lambda (Python 3) 读取存储在 S3 中的 Parquet 文件

jar方式运行项目-读取jar包中的文件

AWS Lambda Python 读取所有行但不写入所有行

怎么从外部读取jar包中的资源文件

jar打包后怎么读取里面的文件