目录:
一、介绍
二、分析问题
三、解决问题
1、如何选择文件夹
2、如何得到文件夹中的文件/自文件夹
3、如何得到文件内容
四、高亮代码
一、介绍
在过去,我们都应该看过很多的教程,都说你如果想在页面去访问文件夹是不可能的,这是用户隐私,像这种用户隐私,浏览器是不会允许开发者去访问的。
但是现在不一样了,现在已经可以访问了,这就得益于一些新的API啦,不过兼容性现在还比较差,不过不影响我们学习。
我们可以看看这个示例。
vscode的这个在线工具,就可以访问你的文件夹,并且还可以看见文件内容,还可以编辑。
那我们也来实现一下,这样的功能。
二、分析问题
要实现上面的功能效果,有4个问题需要我们解决。
1、如何选择文件夹
2、如何得到文件夹中的文件/自文件夹
3、如何得到文件内容
4、如何高亮显示代码
把这几个问题解决,那你想实现上面效果就小意思啦。
三、解决问题
1、如何选择文件夹
就像vscode一样,如何实现点击打开文件夹,就弹出这个选择文件夹弹框呢!
这个问题是最基础的,这个不解决,就没有后续啦。我们来实现一下
<button>打开文件夹</button>
<script>
const btn = document.querySelector('button');
btn.onclick = () => {
// 点击之后展示弹框
}
</script>
我们通过点击按钮,然后去触发弹框,那弹框怎么打开呢。已就是showDirectoryPicker方法。
<script>
const btn = document.querySelector('button');
btn.onclick = () => {
showDirectoryPicker();
}
</script>
这样,弹框就展示出来了,你可以在里面选择任意文件,点击确认。
这个时候浏览器会提示用户,浏览器这个时候想获取用户信息,你是否允许。那你点击运行就好。这样,第一个问题就解决啦。来看看第二个问题
2、如何得到文件夹中的文件/自文件夹
当用户选中一个文件夹之后,我如何拿到这个文件夹里面的文件或者是它的子文件夹。这个如何来做。
我们来仔细研究一下这个函数。showDirectoryPicker这个函数它是一个异步函数,因为它在弹框里面选择需要花时间,肯定是异步的啦。然后我们打印一下,它的值。又因为可能用户拒绝访问会报错,所以用啦trycatch。
<script>
const btn = document.querySelector('button');
btn.onclick = async () => {
try {
// 拿到选择的文件内容
const dir = await showDirectoryPicker();
console.log(dir);
} catch (error) {
// 用户拒绝浏览器访问用户信息
}
}
</script>
我去选择一个文件夹。然后选择,允许查看文件。再看一下控制台。
这个时候,我们发现,kind表示文件类型,name就是文件的名称。
可是我需要拿到子文件|文件夹,我应该怎样拿到呢,通过上面控制台,我们会发现,他有一个entries方法,这个你一看就很熟悉啦,Object也有这个方法对吧,可以拿到对象键值对,那这个地方它的用处也差不多,它可以拿到这个文件下面的所有的文件或者文件夹。
const btn = document.querySelector('button');
btn.onclick = async () => {
try {
// 拿到选择的文件内容
const dir = await showDirectoryPicker();
processDir(dir);
} catch (error) {
// 用户拒绝浏览器访问用户信息
}
}
async function processDir(dir){
const iter = await dir.entries();
console.log(iter);
}
打开控制台,看见它只是一个对象,但是它有一个next方法,有经验的大佬,应该就会联想到JS迭代器和生成器,刚好结果正是如此,它就是一个迭代器,针对迭代器比较熟悉的就是可以使用for of去拿到它的每一项内容啦。
当然,它的迭代器也是异步的,为什么说异步的,因为它相当于是在操作IO,IO操作都几乎是异步的,所以我们来试试。
async function processDir(dir){
const iters = await dir.entries();
for await (const info of iters) {
console.log(info);
}
}
这样,选择的文件下面的文件或文件夹出来了,但是,有可能我的文件下面还有子文件夹,那我也需要拿到才对,所以我们需要递归啦,同时我们也整理一下,因为最终我们得到的是一个树状结构。
const btn = document.querySelector('button');
btn.onclick = async () => {
try {
// 拿到选择的文件内容
const dir = await showDirectoryPicker();
const root = await processDir(dir);
console.log(root);
} catch (error) {
// 用户拒绝浏览器访问用户信息
}
}
async function processDir(dir){
// 文件类型不递归
if(dir.kind === 'file'){
return dir
}
dir.children = []
const iters = await dir.entries();
for await (const info of iters) {
dir.children.push(await processDir(info[1]))
}
return dir
}
这样,我们就可以得到一个树结构的文件啦。到这里,我们就成功拿到选择的文件的文件或子文件夹啦。然后就是来到第三步,如何得到文件内容
3、如何得到文件内容
我们通过查看刚刚得到数据,可以发现,它有一个getFile方法。
const root = await processDir(dir);
const file = await root.children[0].getFile()
console.log(file);
通过打印这个方法返回的内容,你舒服了。得到了文件对象。这个时候一切都好说啦,请大声的告诉我,用什么方法拿到内容。FileReader、FileReader、FileReader。大声说三遍。
const file = await root.children[0].getFile()
const reader = new FileReader();
reader.onload = e => {
console.log(e.target.result);
}
reader.readAsText(file, 'utf-8');
好 很好。这样我们第三步就完成啦。
四、高亮代码
这个我就不展示了,使用highlight.js实现就可以。