基于 Node.js 的文件管理系统(附源码)

fs 模块简介

Node.js 提供一组可用于与文件系统进行交互(以类似于标准 POSIX 函数的方式)的模块 fs 。 使用方式:

const fs = require('fs');

所有的文件系统操作都具有同步的、回调的、以及基于 promise 的形式。

示例

同步

同步的形式会阻塞 Node.js 事件循环和进一步的 JavaScript 执行,直到操作完成。 异常会被立即地抛出,可以使用 try…catch 处理,也可以冒泡。

const fs = require('fs');

try {
    
    
  fs.unlinkSync('文件');
  console.log('已成功删除文件');
} catch (err) {
    
    
  // 处理错误
}

回调

异步的形式总是把完成回调作为其最后一个参数。 传给完成回调的参数取决于具体方法,但第一个参数总是预留给异常。 如果操作被成功地完成,则第一个参数会为 null 或 undefined。(插播一条广告:需要开通正版WebStorm的可以联系我,56元一年,正版授权激活,官网可查有效期,有需要的加我微信:poxiaozhiai6,备注:914。)

const fs = require('fs');

fs.unlink('文件', (err) => {
    
    
  if (err) throw err;
  console.log('已成功删除文件');
});

Promise

基于 promise 的操作会返回 Promise(当异步操作完成时被解决)。

const fs = require('fs');

(async function(path) {
    
    
  try {
    
    
    await fs.unlink(path);
    console.log(`已成功删除 ${
      
      path}`);
  } catch (error) {
    
    
    console.error('出错:', error.message);
  }
})('文件');

文件管理系统

在这里插入图片描述

该示例是基于 nodejs 的一套UI可视化文件管理系统,提供一些常用文件(夹)操作,包含文件(夹) 读取、创建、拷贝、移动、删除、重命名

文件操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bmM9fpOi-1663156319303)(./doc/actions.png)]

读取文件

可读取到文件大小、名称、类型、创建时间、修改时间等。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jIv7Zbsq-1663156319304)(./doc/details.png)]

const readfile = async (dir, filename) => {
    
    
  const fullname = fixpath(`${
      
      dir}/${
      
      filename}`);
  if (!fs.existsSync(fullname)) {
    
    
    throw Error(`[${
      
      fullname}] 文件或文件夹不存在!`);
  }
  const stats = await fs.statSync(fullname);
  if (stats.isFile()) {
    
    
    return {
    
    
      dir,
      filename,
      type: filename.split('.').slice(-1)[0],
      size: stats.size,
      mtime: stats.mtime,
      birthtime: stats.birthtime,
    };
  } else if (stats.isDirectory()) {
    
    
    return {
    
    
      dir,
      filename,
      type: 'dir',
      size: stats.size,
      mtime: stats.ctime,
      birthtime: stats.birthtime,
    };
  }
};

读取文件夹

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b7VEpz2Z-1663156319305)(./doc/dir-actions.png)]

const readdir = async dir => {
    
    
  dir = fixpath(dir);
  if (!fs.existsSync(dir)) {
    
    
    throw Error(`[${
      
      dir}] 文件夹不存在!`);
  }
  const files = await fs.readdirSync(dir);
  const result = [];
  for(let i = 0, l = files.length; i < l; i++) {
    
    
    try {
    
    
      const fileInfo = await readfile(dir, files[i]);
      result.push(fileInfo);
    } catch (err) {
    
    
      continue;
    }
  }
  return result;
};

创建文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WQE8yAOF-1663156319306)(./doc/addfile.png)]

const touch = async (filename, override = true) => {
    
    
  filename = fixpath(filename);
  if (fs.existsSync(filename)) {
    
    
    if (!override) {
    
    
      throw Error(`[${
      
      filename}] 文件已存在!`);
    }
    await rmfile(filename);
  }
  await fs.writeFileSync(filename, '');
  return filename;
};

创建文件夹

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PDypnv2B-1663156319307)(./doc/adddir.png)]

const mkdir = async (dirname, override = true) => {
    
    
  dirname = fixpath(dirname);
  if (fs.existsSync(dirname)) {
    
    
    if (!override) {
    
    
      throw Error(`[${
      
      dirname}] 文件夹已存在!`);
    }
    await rmfile(dirname);
  }
  await fs.mkdirSync(dirname);
  return dirname;
};

拷贝文件(夹)

const copyfile = async (src, dst) => {
    
    
  src = fixpath(src);
  dst = fixpath(dst);
  if (!fs.existsSync(src)) {
    
    
    throw Error(`[${
      
      src}] 文件或文件夹不存在!`);
  }
  const stats = await fs.statSync(src);
  if (stats.isFile()) {
    
    
    const filename = src.split('/').slice(-1)[0];
    let dstfile = `${
      
      dst}/${
      
      filename}`;
    if (fs.existsSync(dstfile)) {
    
    
      dstfile = `${
      
      dst}/${
      
      +new Date()}_${
      
      filename}`;
    }
    await fs.copyFileSync(src, dstfile);
    return dstfile;
  }
  if (stats.isDirectory()) {
    
    
    const filename = src.split('/').slice(-1)[0];
    let dstfile = `${
      
      dst}/${
      
      filename}`;
    if (fs.existsSync(dstfile)) {
    
    
      dstfile = `${
      
      dst}/${
      
      +new Date()}_${
      
      filename}`;
    }
    await fs.mkdirSync(dstfile);
    const files = await fs.readdirSync(src);
    for(let i = 0, l = files.length; i < l; i++) {
    
    
      await copyfile(`${
      
      src}/${
      
      files[i]}`, dstfile);
    }
    return dstfile;
  }
};

删除文件(夹)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lNbiA1g8-1663156319308)(./doc/delete.png)]

const rmfile = async path => {
    
    
  path = fixpath(path);
  if (!fs.existsSync(path)) {
    
    
    throw Error(`[${
      
      path}] 文件或文件夹不存在!`);
  }
  const stats = await fs.statSync(path);
  if (stats.isFile()) {
    
    
    await fs.unlinkSync(path);
    return path;
  }
  if (stats.isDirectory()) {
    
    
    const files = await fs.readdirSync(path);
    for(let i = 0, l = files.length; i < l; i++) {
    
    
      await rmfile(`${
      
      path}/${
      
      files[i]}`);
    }
    await fs.rmdirSync(path);
    return path;
  }
};

移动文件(夹)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PF2gRCZm-1663156319308)(./doc/move.png)]

const movefile = async (src, dst) => {
    
    
  await copyfile(src, dst);
  await rmfile(src);
};

重命名文件(夹)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JKSBq4SG-1663156319309)(./doc/rename.png)]

const rnfile = async (path, newpath) => {
    
    
  newpath = fixpath(newpath);
  path = fixpath(path);
  if (!fs.existsSync(path)) {
    
    
    throw Error(`[${
      
      path}] 文件或文件夹不存在!`);
  }
  fs.renameSync(path, newpath);
};

服务接口

nodejs 服务端文件操作接口

const startServer = app => {
    
    
  app.get('/fs/readdir', async (req, res) => {
    
    
    const {
    
    path} = req.query;
    try {
    
    
      const result = await readdir(path);
      res.status(200).send({
    
    result});
    } catch (error) {
    
    
      res.status(500).send({
    
    message: error.message});
    }
  });
  app.get('/fs/touch', async (req, res) => {
    
    
    const {
    
    path, override} = req.query;
    try {
    
    
      await touch(path, override);
      res.status(200).send({
    
    message: '操作成功!'});
    } catch (error) {
    
    
      res.status(500).send({
    
    error});
    }
  });
  app.get('/fs/rmfile', async (req, res) => {
    
    
    const {
    
    path} = req.query;
    try {
    
    
      await rmfile(path);
      res.status(200).send({
    
    message: '操作成功!'});
    } catch (error) {
    
    
      res.status(500).send({
    
    error});
    }
  });
  ...
};

前端接口配置

const apiList = projectId => [
  {
    
    
    name: 'readfile',
    url: '/readfile',
  },
  {
    
    
    name: 'readdir',
    url: '/readdir',
  },
  {
    
    
    name: 'mkdir',
    url: '/mkdir',
  },
  {
    
    
    name: 'touch',
    url: '/touch',
  },
  {
    
    
    name: 'copyfile',
    url: '/copyfile',
  },
  {
    
    
    name: 'movefile',
    url: '/movefile',
  },
  {
    
    
    name: 'rmfile',
    url: '/rmfile',
  },
  {
    
    
    name: 'rnfile',
    url: '/rnfile',
  },
];

功能函数

窗口最大化

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KKJHG1IE-1663156319310)(./doc/max.png)]

<MaxSize panel={fileRef} target={document.body} />

右键操作菜单

<Drop trigger="contextMenu" dropList={fileDrop(filename)}>
  <div>{filename}</div>
</Drop>

文件单位自动转换

const fixFileSizeUnit = (size, base = 1024) => {
    
    
  const kb = size / base;
  if (kb < base) {
    
    
    return `${
      
      kb.toFixed(3) - 0} KB`;
  }
  const mb = kb / base;
  if (mb < base) {
    
    
    return `${
      
      mb.toFixed(3) - 0} M`;
  }
  const gb = mb / base;
  return `${
      
      gb.toFixed(3) - 0} G`;
};

系统源码下载

下载链接: https://wwb.lanzouy.com/iS2bP0botapa

猜你喜欢

转载自blog.csdn.net/qq_38140936/article/details/126859091
今日推荐