使用AWS JavaScript SDK v2可列出S3 Bucket但无法上传文件求助
AWS SDK v2 上传S3 CredentialsError 问题解决
问题背景
项目依赖限制必须使用AWS JavaScript SDK v2,执行上传文件到S3 Bucket的代码时触发凭证错误,但VSCode终端的AWS CLI可正常完成上传,且代码已配置profile并能正常列出Bucket。
上传代码
const fs = require('fs'); const AWS = require('aws-sdk'); let s3 = new AWS.S3({apiVersion: '2006-03-01'}); const fileName = '/Users/*****/****/*****-ui/**/***/****/BE-Commands/cmd.json'; const uploadFile = () => { fs.readFile(fileName, (err, data) => { if (err) throw err; const params = { Bucket: 'bucket-test', // 替换为你的Bucket名称 Key: 'contacts.csv', // 文件将保存为 bucket-test/contacts.csv Body: JSON.stringify(data, null, 2) }; s3.upload(params, function(s3Err, data) { if (s3Err) throw s3Err console.log(`文件上传成功:${data.Location}`) }); }); }; uploadFile();
报错信息
Error: connect EHOSTDOWN 169.254.169.254:80 - Local (***.1***.1.182:*****) at internalConnect (node:net:1084:16) at defaultTriggerAsyncIdScope (node:internal/async_hooks:465:18) at node:net:1290:9 at process.processTicksAndRejections (node:internal/process/task_queues:77:11) { message: 'Missing credentials in config, if using AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1', errno: -64, code: 'CredentialsError', syscall: 'connect', address: '1****.254.169.254', port: 80, time: 2023-08-10T18:15:50.727Z, originalError: { message: 'Could not load credentials from any providers', errno: -64, code: 'CredentialsError', syscall: 'connect', address: '**********', port: 80, time: 2023-08-10T18:15:50.722Z, originalError: { message: 'EC2 Metadata roleName request returned error', errno: -64, code: 'EHOSTDOWN', syscall: 'connect', address: '***.254.***.***', port: 80, time: 2023-08-10T18:15:50.722Z, originalError: { errno: -64, code: 'EHOSTDOWN', syscall: 'connect', address: '***.***.***.***', port: 80, message: 'connect EHOSTDOWN 169.254.169.254:80 - Local (***.***.1.***:49426)' } } } }
问题原因
报错中的169.254.169.254是EC2实例元数据服务地址,SDK v2在找不到本地凭证时会自动尝试请求该地址获取IAM角色凭证,但本地开发环境无法访问这个地址,因此触发EHOSTDOWN错误。同时SDK v2默认不会加载~/.aws/config中的profile配置,即便你已经配置了profile,也需要显式指定或通过环境变量开启加载。
修复方案
1. 显式指定profile初始化S3客户端
修改S3实例的初始化代码,直接指定要使用的profile名称:
const AWS = require('aws-sdk'); // 替换为你的AWS配置文件中的profile名称 let s3 = new AWS.S3({ apiVersion: '2006-03-01', credentials: new AWS.SharedIniFileCredentials({ profile: '你的profile名' }) });
2. 通过环境变量开启配置加载
在运行代码前设置环境变量AWS_SDK_LOAD_CONFIG=1,让SDK自动加载~/.aws/config中的配置:
- Linux/macOS终端:
export AWS_SDK_LOAD_CONFIG=1 node 你的脚本文件名.js - Windows PowerShell:
$env:AWS_SDK_LOAD_CONFIG=1 node 你的脚本文件名.js
3. 修复文件内容上传错误
代码中使用JSON.stringify(data, null, 2)处理读取的文件数据,而fs.readFile默认返回Buffer,直接转JSON会导致上传的文件内容被篡改。应直接使用读取到的Buffer作为Body:
const params = { Bucket: 'bucket-test', Key: 'contacts.csv', Body: data // 直接用读取到的Buffer,无需JSON.stringify };
内容的提问来源于stack exchange,提问作者Ziwdigforbugs
相关产品推荐
相关产品推荐

