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

部署至Heroku后fs.readdir访问本地路径报错的问题咨询

本地正常但部署到Heroku后出现ENOENT路径错误的解决方法

问题描述

本地开发时,使用Node.js的fs.readdir()访问Windows本地绝对路径,调用localhost:4000/api/readExcelFile接口运行正常;但将项目部署到Heroku后,调用线上接口https://word-word-number.herokuapp.com/api/readExcelFile时,抛出ENOENT错误:

[Error: ENOENT: no such file or directory, scandir 'C:\Users\Kiko Pindoy\Desktop\Island Gas\files\unprocessed'] {
errno: -2,
code: 'ENOENT',
syscall: 'scandir',
path: 'C:\\Users\\Kiko Pindoy\\Desktop\\Island Gas\\files\\unprocessed'}

相关代码:

module.exports.validateFolder = async () => {
    fs.readdir('C:\\Users\\Kiko Pindoy\\Desktop\\Island Gas\\files\\unprocessed', (error, files) => {
        if(error) {
            throw error
        } else {
            if(files.length < 1) {
                let logsPath = 'C:\\Users\\Kiko Pindoy\\Desktop\\Island Gas\\files\\logs\\error'
                let processDate = new Date().toISOString().slice(0, 10)
                let content = `No Files Found in C:\\Users\\Kiko Pindoy\\Desktop\\Island Gas\\files\\unprocessed\n`
                fs.appendFile(`${logsPath}\\${processDate}.txt`, content, error => {
                    if(error) {
                        throw error
                    }
                })
            } else {
                for(let i = 0; i < files.length; i++) {
                    this.validateSheets(`C:\\Users\\Kiko Pindoy\\Desktop\\Island Gas\\files\\unprocessed\\${files[i]}`, files[i])
                }
            }
        }
    })}

问题原因

  1. 硬编码路径不适用于云端环境:Heroku服务器基于Linux系统,没有Windows的C盘用户目录结构,且无法访问你本地电脑的文件系统。
  2. 异步代码逻辑缺陷:async函数内使用回调版fs方法,回调中的throw error无法被外部捕获,错误处理不完整。
  3. 未考虑Heroku文件系统特性:Heroku的本地文件系统是临时存储,服务器重启后所有文件会丢失,不适合持久化业务文件。

解决步骤

1. 替换硬编码路径,使用项目相对路径

放弃Windows本地绝对路径,改用项目内的相对路径,结合path模块处理跨系统路径分隔符:

const path = require('path');
// 项目内的未处理文件目录
const unprocessedDir = path.join(__dirname, 'files', 'unprocessed');
// 项目内的错误日志目录
const logsDir = path.join(__dirname, 'files', 'logs', 'error');

2. 确保目录存在

在读取/写入文件前,先递归创建所需目录,避免因目录不存在报错:

const fs = require('fs').promises;

// recursive: true 会自动创建多级目录
await fs.mkdir(unprocessedDir, { recursive: true });
await fs.mkdir(logsDir, { recursive: true });

3. 修正异步代码逻辑

改用Promise版fs方法配合async/await,确保错误能被正确捕获和处理:

const fs = require('fs').promises;
const path = require('path');

module.exports.validateFolder = async () => {
    const unprocessedDir = path.join(__dirname, 'files', 'unprocessed');
    const logsDir = path.join(__dirname, 'files', 'logs', 'error');

    // 预创建目录
    await fs.mkdir(unprocessedDir, { recursive: true });
    await fs.mkdir(logsDir, { recursive: true });

    try {
        const files = await fs.readdir(unprocessedDir);
        
        if (files.length === 0) {
            const processDate = new Date().toISOString().slice(0, 10);
            const logFilePath = path.join(logsDir, `${processDate}.txt`);
            const content = `No Files Found in ${unprocessedDir}\n`;
            await fs.appendFile(logFilePath, content);
        } else {
            for (const fileName of files) {
                const filePath = path.join(unprocessedDir, fileName);
                // 若validateSheets是异步方法,需用await等待执行完成
                await this.validateSheets(filePath, fileName);
            }
        }
    } catch (err) {
        console.error('处理文件目录失败:', err);
        throw err; // 按需向上抛出错误或自行处理
    }
};

4. 处理文件持久化问题

Heroku本地文件系统是临时的,若需要长期存储文件,建议使用云存储服务(如AWS S3):

  • 实现文件上传接口,将客户端的Excel文件上传到云存储
  • 读取文件时直接从云存储获取,而非依赖服务器本地文件系统

5. 配置Heroku环境变量(可选)

如果需要动态配置文件路径,可在Heroku后台设置环境变量,代码中通过process.env读取:

// 优先读取环境变量,默认使用项目内路径
const unprocessedDir = process.env.FILES_UNPROCESSED_DIR || path.join(__dirname, 'files', 'unprocessed');

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 15:05:35