前端培训-中级阶段(47)- Node.js 10.x文件模块

简介: 前端最基础的就是 HTML+CSS+Javascript。掌握了这三门技术就算入门,但也仅仅是入门,现在前端开发的定义已经远远不止这些。前端小课堂(HTML/CSS/JS),本着提升技术水平,打牢基础知识的中心思想,我们开课啦(每周四)。

使用 Node.js 很大一部分的使用场景是,写个小脚本批量处理一下重复无聊的任务。比如说:


  1. 获取所有 json 内容,然后过滤出想要的数据。


  1. 把所有图片压缩一下,然后放入压缩包中。


  1. 把字体文件提取压缩一下。


  1. 把所有文件重命名一下。


这些任务中我们都需要访问文件系统,之前在浏览器环境中其实是没有文件系统概念的,今天我们来学一哈。


Node.js 文件模块



我们可以使用 fs 来操作文件系统。

const fs = require('fs');


回调方式


所有的文件系统操作都具有同步的(10.x 有,历史也有)、回调的(10.x 有,历史也有)、以及基于 promise(12.x 开始就有了,历史没有) 的形式。


同步


同步的形式会阻止 Node.js 事件循环和进一步的 JavaScript 执行,直到操作完成。

异常会被立即地抛出,可以使用 try…catch 处理,也可以冒泡。


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


异步


异步的形式总是把完成回调作为其最后一个参数。


传给完成回调的参数取决于具体方法,但第一个参数总是预留给异常。 如果操作被成功地完成,则第一个参数会为 nullundefined


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


promise


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


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


文件路径


支持 字符串(常用Path库就对了)、Buffer(为了兼容)、URL(需要 new URL('file:///C:/') 为入参。可以用相对路径 (process.cwd() 可以查看当前路径),绝对路径。


字符串形式


在 Windows 上,Node.js 遵循独立驱动器工作目录的概念。 当使用没有反斜杠的驱动器路径时,可以观察到此行为。 例如, fs.readdirSync('C:\\') 可能会返回与 fs.readdirSync('C:') 不同的结果。 详见此 MSDN 页面


bVcHhwE.webp.jpg


一般我们使用 Path 库:

  1. 可以直接看一下最终地址
  2. 可以正确使用当前系统的路径分隔符,Unix系统是"/",Windows系统是""。


bVcHhw5.webp.jpg


URL 形式


bVcHhyU.webp.jpg


// 在 Windows 上:
// - 带有主机名的 WHATWG 文件的 URL 会转换为 UNC 路径。
// file://主机名/文件 => 主机名文件
fs.readFileSync(new URL('file://主机名/文件'));
// - 带有驱动器号的 WHATWG 文件的 URL 会转换为绝对路径。
// file:///C:/文件 => C:文件
fs.readFileSync(new URL('file:///C:/文件'));


API


目录 dir 类


fs.readdirSync() 同步获取目录


fs.readdir() 异步获取目录


当调用 fs.readdir()fs.readdirSync()withFileTypes 选项设置为 true)时,则生成的数组会使用 fs.Dirent 对象(而不是字符串或 Buffer)填充。

fs.mkdir(path[, options], callback) 异步地创建目录。


回调会传入可能的异常、以及创建的第一个目录的路径(如果 recursivetrue), (err, [path])。可选的 options 参数可以是整数(指定 mode(权限和粘滞位))、或对象(具有 mode 属性和 recursive 属性(指示是否要创建父目录))。


path 是已存在的目录时,调用 fs.mkdir() 仅在 recursive 为 false 时才会导致错误。


fs.mkdirSync(path[, options]) 同步地创建目录。 返回 undefined,或创建的第一个目录的路径(如果 recursivetrue)。 这是 fs.mkdir() 的同步版本。


监听 fs.FSWatcher 类


fs.watch() 每当指定监视的文件被修改时,会触发 'change' 事件。


// 使用 fs.watch()监听器的示例。
fs.watch('./tmp', { 
        encoding: 'buffer'
    }, (eventType, filename) => {
  if (filename) {
    console.log(filename);
  }
});


读取流 fs.ReadStream 类


使用 fs.createReadStream() 函数创建并返回的 fs.ReadStream 实例。


fs.createReadStream(path[, options])




写入流 fs.WriteStream 类


使用 fs.createWriteStream() 函数创建并返回的 fs.WriteStream 实例。

fs.createWriteStream(path[, options])





文件信息 fs.Stats 类


fs.Stats 对象提供了关于文件的信息。在遍历的时候我们会判断文件类型,如果是文件就打开,如果是目录就递归


fs.stat()fs.lstat()fs.fstat()、以及它们的同步方法返回的对象都是此类型。 如果传给这些方法的 options 中的 bigint 为 true,则数值会是 bigint 型而不是 number 型,并且该对象还会包含额外的纳秒级精度的属性(以 Ns 为后缀)。


  1. stats.isDirectory() 如果 fs.Stats 对象描述文件系统目录,则返回 true


  1. stats.isFile() 如果 fs.Stats 对象描述普通的文件,则返回 true


  1. stats.size 文件的大小(以字节为单位)。


  1. stats.mtime 表明上次修改此文件的时间戳。
    stats.mtimeMs 表明上次修改此文件的时间戳,以 POSIX 纪元以来的毫秒数表示。


  1. stats.birthtime 表示此文件的创建时间的时间戳。
    stats.birthtimeMs 表明此文件的创建时间的时间戳,以 POSIX 纪元以来的毫秒数表示。


文件属性的时间值#


中英对照


atimeMsmtimeMsctimeMsbirthtimeMs 属性是保存相应时间(以毫秒为单位)的数值。 它们的精度取决于平台。 当将 bigint: true 传给生成该对象的方法时,属性将会是 bigint 型,否则它们将会是数字型


atimeNsmtimeNsctimeNsbirthtimeNs 属性是保存相应时间(以纳秒为单位)的 bigint。 仅当将 bigint: true 传给生成该对象的方法时,它们才会出现。 它们的精度取决于平台。


atimemtimectimebirthtime 是对应时间的 Date 对象。 Date 值和数值没有关联性。 赋值新的数值、或者改变 Date 的值,都将不会影响到对应的属性。


stat 对象中的时间具有以下语义:

  • atime "访问时间" - 上次访问文件数据的时间。由 mknod(2)utimes(2)read(2) 系统调用更改。




  • birthtime "创建时间" - 创建文件的时间。当创建文件时设置一次。 在不支持创建时间的文件系统上,该字段可能改为保存 ctime1970-01-01T00:00Z(即 Unix 纪元时间戳 0)。 在这种情况下,该值可能大于 atimemtime。 在 Darwin 和其他的 FreeBSD 衍生系统上,也可能使用 utimes(2) 系统调用将 atime 显式地设置为比 birthtime 更早的值。


在 Node.js 0.12 之前,在 Windows 系统上 ctime 保存 birthtime。 从 0.12 开始, ctime 不再是“创建时间”,而在 Unix 系统上则从来都不是。

获取权限访问 fs.access、fs.accessSync


除了判断权限,还可以判断是否存在。不过我们一般可以直接 fs.open() 直接去处理 err 。通常,仅在不直接使用文件时(例如当其可访问性是来自其他进程的信号时),才检查文件的可访问性。


在 Windows 上,目录上的访问控制策略(ACL)可能会限制对文件或目录的访问。 但是, fs.access() 函数不检查 ACL,因此即使 ACL 限制用户读取或写入,也可能报告路径是可访问的。


fs.access(path[, mode], callback)



  • mode<integer> 默认值: fs.constants.F_OK



测试用户对 path 指定的文件或目录的权限。 mode 参数是一个可选的整数,指定要执行的可访问性检查。 查看文件可访问性的常量了解 mode 的可选值。 可以创建由两个或更多个值按位或组成的掩码(例如 fs.constants.W_OK | fs.constants.R_OK)。


文件


  1. fs.open(path[, flags[, mode]], callback) 异步地打开文件。
    fs.openSync(path[, flags, mode]) 同步打开文件


  1. fs.read(fd, buffer, offset, length, position, callback)fd 指定的文件中读取数据,写入到 buffer 中。

fs.readSync(fd, buffer, offset, length, position) 同步版本,从指定 fs 中读取数据


fs.readFile(path[, options], callback) 异步地读取文件的全部内容。
fs.readFileSync(path[, options]) 同步版本,读取文件全部内容


  1. fs.appendFile(path, data[, options], callback) 异步地追加数据到文件,如果文件尚不存在则创建文件。 data 可以是字符串或 Buffer

fs.appendFileSync(path, data[, options]) 同步地将数据追加到文件,如果文件尚不存在则创建该文件。 data 可以是字符串或 Buffer


// 直接针对文件追加
fs.appendFileSync('文件.txt', '追加的数据', 'utf8');
// 先打开文件,然后针对文件描述符追加
fd = fs.openSync('文件.txt', 'a');
fs.appendFileSync(fd, '追加的数据', 'utf8');


  1. fs.copyFile(src, dest[, mode], callback) 异步地将 src 拷贝到 dest。 默认情况下,如果 dest 已经存在,则覆盖它。 除了可能的异常,回调函数没有其他参数。 Node.js 不保证拷贝操作的原子性。 如果在打开目标文件用于写入后发生错误,则 Node.js 将尝试删除目标文件。

fs.copyFileSync(src, dest[, mode]) 同步


  1. fs.rename(oldPath, newPath, callback) 异步地把 oldPath 文件重命名为 newPath 提供的路径名。 如果 newPath 已存在,则覆盖它。 除了可能的异常,完成回调没有其他参数。

fs.renameSync(oldPath, newPath) 同步版本,文件重命名


  1. fs.write(fd, buffer[, offset[, length[, position]]], callback) 写入 bufferfd 指定的文件。不等待回调就对同一个文件多次使用 fs.write() 是不安全的。 对于这种情况,建议使用 fs.createWriteStream()


示例



获取目录下所有图片,并上传到服务器


const FormData = require('form-data');
const fetch = require('node-fetch');
var fs = require('fs');
var path = require('path');
var dirPath = 'cdn-transform'
var filePath = path.resolve(`./node-upload-img/${dirPath}`);
//文件遍历方法
function fileDisplay(filePath){
    fs.readdir(filePath,function(err,files){
        if(err){
            console.warn(err)
        }else{
            files.forEach(function(filename){
                var filedir = path.join(filePath, filename);
                var buffer = fs.readFileSync(filedir)
                var formData = new FormData();
                var fileName = `${filename}`
                var url =  `www.lilnong.top/upload/fe-up/${dirPath}/${fileName}`;
                formData.append('file', buffer, `${fileName}`);
                fetch('http://www.lilnong.top/upload',{
                    headers: formData.getHeaders(),
                    method: 'post',
                    body: formData
                })
                .then(v=>v.text())
                .then(v=>{
                    console.log('http://www.lilnong.top/upload', url, v)
                })
            })
        }
    });
}
fileDisplay(filePath)


递归遍历所有json


const readDir = (entry, paths = []) => {
    const dirInfo = fs.readdirSync(entry);
    dirInfo.forEach(item=>{
        const location = path.join(entry,item);
        const info = fs.statSync(location);
        if(info.isDirectory()){
            console.log(`dir:${location}`);
            readDir(location, [item]);
        }else{
            if(/.json$/.test(location)){
                readFile(location, paths)
            }
        }
    })
}
console.log('__dirname', __dirname)
readDir(__dirname);
function readFile(path, pathKey){
    return console.log(path, pathKey);
})


相关文章
|
JavaScript 前端开发
在Node.js中,如何合理使用模块来避免全局变量的问题?
在Node.js中,如何合理使用模块来避免全局变量的问题?
674 167
|
JSON 自然语言处理 前端开发
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
827 72
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
|
Dart 前端开发
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
622 75
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
JavaScript 前端开发 API
|
编解码 JavaScript 前端开发
如何在网页播放英文的m3u8文件(基于Javascript搭建的在线网页工具)
什么是m3u8?又该如何在网页中高效、便捷地播放英文的m3u8文件呢?今天这篇文章就带你一起了解,并推荐一种基于Javascript搭建的在线网页工具,让你轻松解决播放问题。
4050 0
|
JavaScript 前端开发 开发者
Node学习笔记:HTTP模块
总的来说,Node.js的HTTP模块是一个强大的工具,可以帮助你处理HTTP协议的各种需求。无论你是想开设自己的餐厅(创建服务器),还是想去别的餐厅点菜(发出请求),HTTP模块都能满足你的需求。
435 18
|
前端开发 Cloud Native Java
Java||Springboot读取本地目录的文件和文件结构,读取服务器文档目录数据供前端渲染的API实现
博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
Java||Springboot读取本地目录的文件和文件结构,读取服务器文档目录数据供前端渲染的API实现
|
前端开发 JavaScript 数据可视化
58K star!这个让网页动起来的JS库,前端工程师直呼真香!
Anime.js 是一款轻量级但功能强大的JavaScript动画引擎,它能够以最简单的方式为网页元素添加令人惊艳的动效。这个项目在GitHub上已经获得58,000+星标,被广泛应用于电商页面、数据可视化、游戏开发等场景。
848 8
|
资源调度 JavaScript 前端开发
前端开发必备!Node.js 18.x LTS保姆级安装教程(附国内镜像源配置)
本文详细介绍了Node.js的安装与配置流程,涵盖环境准备、版本选择(推荐LTS版v18.x)、安装步骤(路径设置、组件选择)、环境验证(命令测试、镜像加速)及常见问题解决方法。同时推荐开发工具链,如VS Code、Yarn等,并提供常用全局包安装指南,帮助开发者快速搭建高效稳定的JavaScript开发环境。内容基于官方正版软件,确保合规性与安全性。
16412 23
|
前端开发
【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
1339 1
【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布

热门文章

最新文章

  • 1
    前端如何存储数据:Cookie、LocalStorage 与 SessionStorage 全面解析
    1375
  • 2
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(九):强势分析Animation动画各类参数;从播放时间、播放方式、播放次数、播放方向、播放状态等多个方面,完全了解CSS3 Animation
    647
  • 3
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(八):学习transition过渡属性;本文学习property模拟、duration过渡时间指定、delay时间延迟 等多个参数
    504
  • 4
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(七):学习ransform属性;本文学习 rotate旋转、scale缩放、skew扭曲、tanslate移动、matrix矩阵 多个参数
    507
  • 5
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(六):全方面分析css的Flex布局,从纵、横两个坐标开始进行居中、两端等元素分布模式;刨析元素间隔、排序模式等
    613
  • 6
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(五):背景属性;float浮动和position定位;详细分析相对、绝对、固定三种定位方式;使用浮动并清除浮动副作用
    793
  • 7
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(四):元素盒子模型;详细分析边框属性、盒子外边距
    1574
  • 8
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(三):元素继承关系、层叠样式规则、字体属性、文本属性;针对字体和文本作样式修改
    366
  • 9
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(二):CSS伪类:UI伪类、结构化伪类;通过伪类获得子元素的第n个元素;创建一个伪元素展示在页面中;获得最后一个元素;处理聚焦元素的样式
    1287
  • 10
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(一):CSS发展史;CSS样式表的引入;CSS选择器使用,附带案例介绍
    625