Node.js中fs.readdir与readFile无回调版本查询及目录文件上传S3实现
问题解答
Node.js的fs模块官方原生提供了无需回调的同类方法,完全可以适配你的使用场景:
无回调方法说明
- 读取目录对应方法:
fs.promises.readdir(path[, options]),直接使用await调用即可返回目录下的文件名称数组,无需传入回调函数 - 读取文件对应方法:
fs.promises.readFile(path[, options]),同样支持await调用直接返回文件内容
你也可以用Node.js内置的util.promisify工具手动把原有回调式方法转成Promise风格,但更推荐直接使用官方封装好的fs.promises系列方法,兼容性和稳定性更好。
适配你场景的优化后可运行代码
你原来的代码存在逻辑缺陷:虽然给readFiles1加了async标识,但内部还是用回调写法,外部的await readFiles1不会等待内部读目录、读文件、上传操作全部完成就会继续执行。优化后代码如下:
const fs = require('fs').promises // 直接引入Promise版本的fs接口 const path = require('path') // 用path拼接路径避免跨平台兼容问题 const AWS = require('aws-sdk') const express = require('express') const app = express() const s3Upload = async (req, res) => { const directoryName = "MAXIS_GAMING/Daily/" try { await readFiles1(directoryName) res.send('所有文件上传完成') } catch (err) { console.error('处理流程出错:', err) res.status(500).send('上传失败:' + err.message) } } const readFiles1 = async(dirname) => { // await读取目录 const files = await fs.readdir(dirname) console.log('目录下文件列表:', files.join(' ')) // 批量生成读文件+上传的异步任务 const uploadTasks = files.map(async (filename) => { const fullFilePath = path.join(dirname, filename) // await读取文件内容 const content = await fs.readFile(fullFilePath, 'utf-8') console.log('读取文件完成:', filename) // await执行上传 await uploadFiles(filename, content) }) // 等待所有文件上传完成 await Promise.all(uploadTasks) } const uploadFiles = async (fileName, fileContent) => { console.log('开始上传文件:', fileName) const GLOBAL_ACCESS_KEY_ID = 'AKIDAQWZX6B3XUBDIFHLPC5LYFTJF15XPIQ'; const GLOBAL_SECRET_ACCESS_KEY = 'Sv4Fe4h4QgErG5XoZbgeC63oczkdW3bMQfC0jvyR8bPbJ9Y97k+' const GLOBAL_DEFAULT_REGION = 'ap-southeast-1'; const S3_IMAGE_BUCKET ='max-stg-image/stage/reports' AWS.config.update({ accessKeyId: GLOBAL_ACCESS_KEY_ID, secretAccessKey: GLOBAL_SECRET_ACCESS_KEY, region: GLOBAL_DEFAULT_REGION, }); const s3 = new AWS.S3() const params = { Bucket: S3_IMAGE_BUCKET, Key: fileName, Body: fileContent }; // 将回调式的s3.upload封装为Promise风格支持await return new Promise((resolve, reject) => { s3.upload(params, function(err, data) { if (err) return reject(err); console.log(`文件上传成功: ${data.Location}`); resolve(data) }); }) } app.get('/home/s3Upload', s3Upload) // 自行补充服务启动逻辑即可,如:app.listen(3000, () => console.log('服务启动'))
优化说明
- 所有异步操作都支持同步等待,解决了你原来代码中
await不生效的问题 - 统一用
try/catch捕获全局异常,不需要在每个回调里单独处理错误 - 用path模块拼接路径,避免斜杠漏写、跨平台路径分隔符不兼容的问题
- 如果目录下文件较多不想并发太高,可以把
Promise.all替换为普通for循环逐个执行,控制并发量
内容的提问来源于stack exchange,提问作者krishna kurtakoti
相关产品推荐
相关产品推荐

