前端最根底的就是 HTML+CSS+Javascript
。把握了这三门技术就算入门,但也仅仅是入门,当初前端开发的定义曾经远远不止这些。前端小课堂(HTML/CSS/JS
),本着晋升技术水平,打牢基础知识的中心思想,咱们开课啦(每周四)。
应用 Node.js 很大一部分的应用场景是,写个小脚本批量解决一下反复无聊的工作。比如说:
- 获取所有 json 内容,而后过滤出想要的数据。
- 把所有图片压缩一下,而后放入压缩包中。
- 把字体文件提取压缩一下。
- 把所有文件重命名一下。
这些工作中咱们都须要拜访文件系统,之前在浏览器环境中其实是没有文件系统概念的,明天咱们来学一哈。
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) { // 处理错误}
异步
异步的模式总是把实现回调作为其最初一个参数。
传给实现回调的参数取决于具体方法,但第一个参数总是预留给异样。 如果操作被胜利地实现,则第一个参数会为 null
或 undefined
。
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 页面。
个别咱们应用 Path 库:
- 能够间接看一下最终地址
- 能够正确应用以后零碎的门路分隔符,Unix零碎是"/",Windows零碎是""。
URL 模式
// 在 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)
异步地创立目录。回调会传入可能的异样、以及创立的第一个目录的门路(如果 recursive
为 true
), (err, [path])
。可选的 options
参数能够是整数(指定 mode
(权限和粘滞位))、或对象(具备 mode
属性和 recursive
属性(批示是否要创立父目录))。 当 path
是已存在的目录时,调用 fs.mkdir()
仅在 recursive
为 false 时才会导致谬误。fs.mkdirSync(path[, options])
同步地创立目录。 返回 undefined
,或创立的第一个目录的门路(如果 recursive
为 true
)。 这是 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])
path
<string> | <Buffer> | <URL>options
<string> | <Object>flags
<string> 参见文件系统flag
的反对。 默认值:'r'
。encoding
<string> 默认值:null
。fd
<integer> 默认值:null
。mode
<integer> 默认值:0o666
。autoClose
<boolean> 默认值:true
。emitClose
<boolean> 默认值:false
。start
<integer>end
<integer> 默认值:Infinity
。highWaterMark
<integer> 默认值:64 * 1024
。fs
<Object> | <null> 默认值:null
。
- 返回: <fs.ReadStream> 参见可读流。
写入流 fs.WriteStream 类
应用 fs.createWriteStream()
函数创立并返回的 fs.WriteStream
实例。
fs.createWriteStream(path[, options])
path
<string> | <Buffer> | <URL>options
<string> | <Object>flags
<string> 参见文件系统flag
的反对。 默认值:'w'
。encoding
<string> 默认值:'utf8'
。fd
<integer> 默认值:null
。mode
<integer> 默认值:0o666
。autoClose
<boolean> 默认值:true
。emitClose
<boolean> 默认值:false
。start
<integer>fs
<Object> | <null> 默认值:null
。
- 返回: <fs.WriteStream> 参见可写流。
,.
文件信息 fs.Stats 类
fs.Stats
对象提供了对于文件的信息。在遍历的时候咱们会判断文件类型,如果是文件就关上,如果是目录就递归
从 fs.stat()
、fs.lstat()
、fs.fstat()
、以及它们的同步办法返回的对象都是此类型。 如果传给这些办法的 options
中的 bigint
为 true,则数值会是 bigint
型而不是 number
型,并且该对象还会蕴含额定的纳秒级精度的属性(以 Ns
为后缀)。
stats.isDirectory()
如果fs.Stats
对象形容文件系统目录,则返回true
。stats.isFile()
如果fs.Stats
对象形容一般的文件,则返回true
。stats.size
文件的大小(以字节为单位)。stats.mtime
表明上次批改此文件的工夫戳。stats.mtimeMs
表明上次批改此文件的工夫戳,以 POSIX 纪元以来的毫秒数示意。stats.birthtime
示意此文件的创立工夫的工夫戳。stats.birthtimeMs
表明此文件的创立工夫的工夫戳,以 POSIX 纪元以来的毫秒数示意。
文件属性的工夫值#
中英对照
atimeMs
、mtimeMs
、ctimeMs
和birthtimeMs
属性是保留相应工夫(以毫秒为单位)的数值。 它们的精度取决于平台。 当将bigint: true
传给生成该对象的办法时,属性将会是 bigint 型,否则它们将会是数字型。
atimeNs
、mtimeNs
、ctimeNs
和birthtimeNs
属性是保留相应工夫(以纳秒为单位)的 bigint。 仅当将bigint: true
传给生成该对象的办法时,它们才会呈现。 它们的精度取决于平台。
atime
、mtime
、ctime
和birthtime
是对应工夫的Date
对象。Date
值和数值没有关联性。 赋值新的数值、或者扭转Date
的值,都将不会影响到对应的属性。stat 对象中的工夫具备以下语义:
atime
"拜访工夫" - 上次访问文件数据的工夫。由mknod(2)
、utimes(2)
和read(2)
零碎调用更改。mtime
"批改工夫" - 上次批改文件数据的工夫。由mknod(2)
、utimes(2)
和write(2)
零碎调用更改。ctime
"更改工夫" - 上次更改文件状态(批改索引节点数据)的工夫。由chmod(2)
、chown(2)
、link(2)
、mknod(2)
、rename(2)
、unlink(2)
、utimes(2)
、read(2)
和write(2)
零碎调用更改。birthtime
"创立工夫" - 创立文件的工夫。当创立文件时设置一次。 在不反对创立工夫的文件系统上,该字段可能改为保留ctime
或1970-01-01T00:00Z
(即 Unix 纪元工夫戳0
)。 在这种状况下,该值可能大于atime
或mtime
。 在 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)
path
<string> | <Buffer> | <URL>mode
<integer> 默认值:fs.constants.F_OK
。callback
<Function>err
<Error>
测试用户对 path
指定的文件或目录的权限。 mode
参数是一个可选的整数,指定要执行的可拜访性查看。 查看文件可拜访性的常量理解 mode
的可选值。 能够创立由两个或更多个值按位或组成的掩码(例如 fs.constants.W_OK | fs.constants.R_OK
)。
文件
fs.open(path[, flags[, mode]], callback)
异步地关上文件。fs.openSync(path[, flags, mode])
同步关上文件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])
同步版本,读取文件全部内容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');
fs.copyFile(src, dest[, mode], callback)
异步地将src
拷贝到dest
。 默认状况下,如果dest
曾经存在,则笼罩它。 除了可能的异样,回调函数没有其余参数。 Node.js 不保障拷贝操作的原子性。 如果在关上指标文件用于写入后产生谬误,则 Node.js 将尝试删除指标文件。fs.copyFileSync(src, dest[, mode])
同步fs.rename(oldPath, newPath, callback)
异步地把oldPath
文件重命名为newPath
提供的路径名。 如果newPath
已存在,则笼罩它。 除了可能的异样,实现回调没有其余参数。fs.renameSync(oldPath, newPath)
同步版本,文件重命名fs.write(fd, buffer[, offset[, length[, position]]], callback)
写入buffer
到fd
指定的文件。不期待回调就对同一个文件屡次应用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);})
微信公众号:前端linong
参考文献
- 前端培训目录、前端培训布局、前端培训打算
- http://nodejs.cn/api/fs.html#fs_file_paths