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

如何删除嵌套文件夹中的指定文件(Node.js+Express场景)

Node.js+Express 删除嵌套目录本地文件路径问题解决

问题场景

在Node.js+Express项目中,需要先删除数据库中指定文件的记录,再删除uploads目录下嵌套子文件夹中的对应本地文件。但使用fs.unlinkSync、fs.access等方法时始终报错,核心问题是生成的文件路径错误,无法匹配到目标文件。

用户原代码:

import Express from 'express';
import { baseURL } from '..';
import fs from 'fs';
import path from 'path';
import { GuestFile } from '../models/guest-file';

export const GuestDelete = async (request: Express.Request, response: Express.Response) => {
const { identifier } = request.params;

const find_file = await GuestFile.findOne({ identifier });

if (!find_file) {
return response.status(404).json({ error: 'File not found', success: false });
}

const local_file_path = find_file.file_url?.split(`${baseURL}`).pop();
const file_name = local_file_path?.split('/')?.splice(-1)[0];

// 问题出在这里
fs.readdirSync(path.join(__dirname + `/uploads/${find_file.type}s/`)).find((file) => console.log(file));

console.log('file_name', file_name);

response.status(204).json({ success: true, identifier });
};

曾尝试的无效代码:

fs.readdirSync('/uploads/${find_file.type}/').find((file) => file === file_name && fs.unlinkSync(file_name));

当前生成的错误路径:

C:\Users\essel_r\Desktop\everfile\backend_api\src\controllers\uploads\images\

目录结构说明:项目根目录为everfile/backend_api,uploads目录直接位于根目录下(而非src/controllers子目录中),uploads下按文件类型分了子文件夹(比如images)。

错误原因

  1. 路径拼接错误:__dirname指向当前控制器文件所在的src/controllers目录,直接拼接/uploads/...会把uploads放到controllers目录下,与实际目录结构不符。
  2. 相对路径使用错误:直接用/uploads/${find_file.type}/是系统根目录的绝对路径,而非项目根目录下的uploads。
  3. 删除文件时路径不完整:调用fs.unlinkSync(file_name)只传了文件名,没有完整的文件路径,导致系统找不到文件。

解决方案

步骤1:正确获取项目根目录下的uploads路径

利用path.resolve从当前文件向上回溯到项目根目录,再拼接uploads和类型子文件夹。

步骤2:拼接完整的目标文件路径

结合类型子文件夹和文件名,生成完整的本地文件路径。

步骤3:检查文件存在后再删除

先使用fs.existsSync检查文件是否存在,避免删除不存在的文件报错。

步骤4:删除数据库记录(可根据业务调整执行顺序)

修改后的完整代码:

import Express from 'express';
import { baseURL } from '..';
import fs from 'fs';
import path from 'path';
import { GuestFile } from '../models/guest-file';

export const GuestDelete = async (request: Express.Request, response: Express.Response) => {
  const { identifier } = request.params;

  try {
    // 查询数据库记录
    const find_file = await GuestFile.findOne({ identifier });
    if (!find_file) {
      return response.status(404).json({ error: '文件不存在', success: false });
    }

    // 解析文件名(从file_url中提取)
    const local_file_path = find_file.file_url?.split(`${baseURL}`).pop();
    const file_name = local_file_path?.split('/')?.pop();
    if (!file_name) {
      return response.status(400).json({ error: '文件路径解析失败', success: false });
    }

    // 生成正确的本地文件目录路径
    // 从当前文件(src/controllers)向上两级到项目根目录,再拼接uploads和类型子文件夹
    const uploadsDir = path.resolve(__dirname, '../../uploads', `${find_file.type}s`);
    // 生成完整的文件路径
    const fullFilePath = path.join(uploadsDir, file_name);

    // 检查文件是否存在并删除
    if (fs.existsSync(fullFilePath)) {
      fs.unlinkSync(fullFilePath);
    } else {
      console.warn(`文件 ${fullFilePath} 不存在,跳过删除`);
    }

    // 删除数据库记录
    await GuestFile.deleteOne({ identifier });

    return response.status(200).json({ success: true, identifier });
  } catch (error) {
    console.error('删除文件或数据库记录失败:', error);
    return response.status(500).json({ error: '服务器内部错误', success: false });
  }
};

关键说明

  • 使用path.resolve和path.join拼接路径,避免Windows与Linux路径分隔符的兼容性问题。
  • 增加异常捕获,处理文件删除或数据库操作时的错误,避免服务崩溃。
  • 可根据业务需求调整流程顺序:比如先删数据库记录再删文件,但需考虑失败场景的回滚逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 19:50:17