当前位置: 首页 > web >正文

nodejs 文件的复制

在 Node.js 中,文件复制操作可以通过多种方式实现,具体取决于文件大小、性能需求以及是否需要保留文件元数据(如权限、时间戳等)。以下是几种常见的文件复制方法及其示例代码:

1. 使用 fs.copyFile(简单高效)

这是 Node.js 提供的最简单的文件复制方法,适用于大多数场景。

const fs = require('fs');const sourcePath = 'source.txt';
const targetPath = 'destination.txt';// 异步复制(推荐)
fs.copyFile(sourcePath, targetPath, (err) => {if (err) {console.error('复制失败:', err);return;}console.log('文件复制成功');
});// 同步复制
try {fs.copyFileSync(sourcePath, targetPath);console.log('文件同步复制成功');
} catch (err) {console.error('同步复制失败:', err);
}

选项参数

  • fs.constants.COPYFILE_EXCL:若目标文件已存在则失败(不覆盖)。
  • fs.constants.COPYFILE_FICLONE:使用克隆(如果支持)。
// 示例:不覆盖已存在的文件
fs.copyFile(sourcePath, targetPath, fs.constants.COPYFILE_EXCL, (err) => {if (err && err.code === 'EEXIST') {console.log('目标文件已存在,跳过复制');}
});

2. 使用流(Stream)处理大文件

对于大文件,使用流可以避免内存溢出,提高效率。

const fs = require('fs');const sourcePath = 'large-file.zip';
const targetPath = 'large-file-copy.zip';// 创建可读流和可写流
const readStream = fs.createReadStream(sourcePath);
const writeStream = fs.createWriteStream(targetPath);// 管道流(自动处理数据传输和错误)
readStream.pipe(writeStream);// 监听完成和错误事件
readStream.on('error', (err) => {console.error('读取源文件失败:', err);
});writeStream.on('error', (err) => {console.error('写入目标文件失败:', err);
});writeStream.on('finish', () => {console.log('大文件复制完成');
});

更健壮的流复制实现

async function copyFileWithStream(source, target) {return new Promise((resolve, reject) => {const readStream = fs.createReadStream(source);const writeStream = fs.createWriteStream(target);readStream.on('error', reject);writeStream.on('error', reject);writeStream.on('finish', resolve);readStream.pipe(writeStream);});
}// 使用示例
copyFileWithStream('source.txt', 'target.txt').then(() => console.log('复制成功')).catch((err) => console.error('复制失败:', err));

3. 手动读取写入(不推荐,仅作演示)

不推荐使用此方法,因为它会一次性将整个文件加载到内存中,适用于小文件。

const fs = require('fs');// 异步
fs.readFile('source.txt', (err, data) => {if (err) {console.error('读取文件失败:', err);return;}fs.writeFile('destination.txt', data, (err) => {if (err) console.error('写入文件失败:', err);else console.log('文件复制成功');});
});// 同步
try {const data = fs.readFileSync('source.txt');fs.writeFileSync('destination.txt', data);console.log('文件同步复制成功');
} catch (err) {console.error('同步复制失败:', err);
}

4. 保留文件元数据(权限、时间戳)

如果需要保留文件的原始权限和时间戳,可以在复制后设置:

const fs = require('fs');async function copyFileWithMetadata(source, target) {try {// 复制文件await fs.promises.copyFile(source, target);// 获取源文件的状态const stat = await fs.promises.stat(source);// 设置目标文件的权限await fs.promises.chmod(target, stat.mode);// 设置目标文件的时间戳await fs.promises.utimes(target, stat.atime, stat.mtime);console.log('文件复制完成,元数据已保留');} catch (err) {console.error('复制失败:', err);}
}// 使用示例
copyFileWithMetadata('source.txt', 'target.txt');

5. 递归复制目录(含子文件和子目录)

如果需要复制整个目录及其内容,可以使用递归方法:

const fs = require('fs').promises;
const path = require('path');async function copyDirectory(sourceDir, targetDir) {try {// 创建目标目录(递归选项确保父目录存在)await fs.mkdir(targetDir, { recursive: true });// 读取源目录内容const entries = await fs.readdir(sourceDir, { withFileTypes: true });// 遍历目录内容for (const entry of entries) {const sourcePath = path.join(sourceDir, entry.name);const targetPath = path.join(targetDir, entry.name);if (entry.isDirectory()) {// 递归复制子目录await copyDirectory(sourcePath, targetPath);} else {// 复制文件await fs.copyFile(sourcePath, targetPath);}}console.log(`目录 ${sourceDir} 已复制到 ${targetDir}`);} catch (err) {console.error('复制目录失败:', err);}
}// 使用示例
copyDirectory('./src', './dist');

总结

  • 小文件:直接使用 fs.copyFile
  • 大文件:使用流(createReadStream + createWriteStream)。
  • 递归复制目录:使用递归函数结合 fs.readdirfs.copyFile
  • 保留元数据:复制后使用 chmodutimes 设置权限和时间戳。

根据具体需求选择合适的方法,确保处理好错误情况和边缘场景(如文件已存在、权限不足等)。

http://www.xdnf.cn/news/7028.html

相关文章:

  • 【人工智能】微调的艺术:将大模型塑造成你的专属智能助手
  • 大模型技术演进与应用场景深度解析
  • Type-C连接器:数字时代接口革命的终极答案
  • C语言中字符串函数的详细讲解
  • 2025年数字孪生技术最新应用案例:跨领域实践与技术趋势
  • OpenAI新发布Codex的全面解析
  • C语言输入函数对比解析
  • GPIO点亮LED
  • 使用UniApi调用百度地图API的需要注意的地方
  • 基于 jQuery 的轻量级在线画册、电子书、产品目录插件及使用
  • 粒子群算法(PSO算法)
  • RAGFlow Arbitrary Account Takeover Vulnerability
  • 广东省省考备考(第十三天5.17)—言语:中心理解题(听课后强化练习)
  • 3、ubantu系统 | 通过vscode远程安装并配置anaconda
  • C++中析构函数不设为virtual导致内存泄漏示例
  • 电子电路:电位器和可变电阻是同一个东西吗?
  • 2025年【道路运输企业安全生产管理人员】考试题库及道路运输企业安全生产管理人员考试内容
  • 获取淘宝店铺所有商品信息接口数据指南
  • JavaScript splice() 方法
  • 【C++】string的使用【上】
  • Linux面试题集合(6)
  • PIC16F18877 ADC 代码
  • Python绘制南丁格尔玫瑰图:从入门到实战
  • 专题四:综合练习(组合总和的暴搜dfs)
  • printf耗时高的原因
  • UE 材质基础 第一天
  • nginx集成防火墙ngx_waf的docker版
  • 重庆 ICPC 比赛游记
  • Vue 3.0中响应式依赖和更新
  • list重点接口及模拟实现