【问题标题】:reading a packaged file in aws lambda package读取 aws lambda 包中的打包文件
【发布时间】: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

标签: node.js amazon-web-services lambda aws-lambda


【解决方案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_ROOTcomment。当我在我的机器上使用 __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 不区分大小写!!!....

        【讨论】:

          猜你喜欢
          • 2019-08-07
          • 1970-01-01
          • 2018-06-02
          • 1970-01-01
          • 2023-03-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多