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

fs.readdirSync无法读取文件夹文件?Node.js图片处理类问题排查

问题原因及解决方案

核心问题分析

  1. forEach不支持异步等待
    你在getImages里用了forEach(async (link, i) => { ... }),但forEach本质是同步遍历,它不会等待内部的异步操作完成——不管里面写了多少await,forEach都会直接遍历完所有元素后立刻返回。这导致getImages虽然标记了async,但实际会在所有下载任务启动前就结束,saveImages里的await等于无效,uploadImages会在图片还没下载完成(甚至还没开始写入磁盘)时就执行,自然读不到文件。

  2. 流写入未等待完成
    就算解决了forEach的问题,pipe(fs.createWriteStream(fileLocation))是异步写入操作:await axios(...)只代表请求的响应头和部分数据已拿到,不代表文件已经完全写入磁盘。这时候去读目录,文件可能还处于写入中状态,依然会返回空数组。


修复代码

1. 修复getImages函数

用map+Promise.all替代forEach,同时将流写入封装为Promise等待完成:

export const getImages = async (
  links: string[],
  folder: string,
  extra?: string
) => {
  // 用map生成异步任务数组,Promise.all等待所有任务完成
  await Promise.all(links.map(async (link, i) => {
    const fileLocation = path.resolve(
      folder,
      extra ? extra : "",
      `image${i}.jpeg`
    );

    const response = await axios({
      method: "get",
      url: extractImageUrl(link),
      responseType: "stream",
    });

    // 封装流写入为Promise,等待finish事件确认文件写入完成
    await new Promise<void>((resolve, reject) => {
      response.data
        .pipe(new ExifTransformer())
        .pipe(fs.createWriteStream(fileLocation))
        .on("finish", () => resolve())
        .on("error", (err) => reject(err));
    });
  }));
};

2. 简化主函数调用(可选)

不需要混用await和then,直接顺序执行更清晰:

const main = async (url: string) => {
  const id = uid(5);
  const IH = new imageHandler(id, imageFolder);

  await IH.saveImages(data?.images);
  IH.uploadImages();
};

额外排查建议

  • 临时测试:可以在uploadImages前加await new Promise(resolve => setTimeout(resolve, 2000)),如果延迟后能读到文件,就坐实了异步操作未等待的问题。
  • 路径校验:在getImages里打印fileLocation,和uploadImages里的jobFolder对比,确保两者路径完全一致(避免相对路径/绝对路径混用导致的目录不匹配)。
  • 权限检查:确认程序拥有目标目录的读写权限(不过你手动能看到文件,大概率不是这个问题)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 08:02:06