Node.js调用fs.copyFile在挂载目录复制文件报ENOTSUP socket错误如何解决
问题原因分析
- 待复制的文件列表中包含socket、命名管道、设备文件等特殊文件类型,Node.js原生
fs.copyFile仅支持复制普通常规文件,无法处理这类特殊文件。 - 操作的目录属于网络挂载文件系统(如SMB、NFS、sshfs等),
fs.copyFile底层默认调用的copy_file_range系统调用对跨挂载点、网络文件系统的兼容性较差,会触发该类报错。 - 原有代码存在逻辑问题:
chmod修改的是源文件权限,如果你需要给目标文件设置777权限,需要改为修改目标路径的权限。
可行解决方案
方案1:先过滤特殊文件再复制
适用于文件列表混入特殊文件的场景,复制前先校验文件类型,仅处理普通文件:
const fs = require('fs/promises'); const path = require('path'); async ({ destDir, files }) => { return await Promise.all( files.map(async (filePath) => { const stat = await fs.lstat(filePath); // 只处理普通文件,跳过socket、目录、链接、管道等特殊文件 if (!stat.isFile()) return; const fileName = path.basename(filePath); const destPath = path.join(destDir, fileName); await fs.copyFile(filePath, destPath); // 给目标文件设置777权限 await fs.chmod(destPath, "777"); }) ); }
方案2:改用流方式复制文件
适用于网络挂载目录场景,规避copy_file_range系统调用的兼容性问题:
const fs = require('fs'); const path = require('path'); const { pipeline } = require('stream/promises'); async ({ destDir, files }) => { return await Promise.all( files.map(async (filePath) => { const stat = await fs.promises.lstat(filePath); if (!stat.isFile()) return; const fileName = path.basename(filePath); const destPath = path.join(destDir, fileName); // 用流复制,替代copyFile await pipeline( fs.createReadStream(filePath), fs.createWriteStream(destPath, { mode: 0o777 }) ); }) ); }
如果需要确保权限生效,可在流复制完成后额外调用fs.chmod修改目标文件权限。
内容的提问来源于stack exchange,提问作者Valu3
相关产品推荐
相关产品推荐

