文章背景
之前公司有一个需要读取本地文件视频的需求,但是在我们最初学习js的时候,老师讲的是无法读取文件夹,这里有个误区,技术是一直在迭代,好吧,是我out了。然后我直接告诉产品这个需求无法实现,最终解决的方案是后端的兄弟采用Go写的一个本地服务器来读取的。后来偶然在网上发现了vscode居然有个网页编辑器,这个就打开我的新世界了,既然有网页版的编辑器,那么必然需要读取本地的文件,经过我了解,现代的浏览器确实可以实现,但是目前还会有一些兼容性的问题有待提升,话不多说,往下看!!
本章需要了解的技术点
// 文档地址:https://developer.mozilla.org/zh-CN/
window.showDirectoryPicker() // 用于显示一个目录选择器,以允许用户选择一个目录。
Object.entries() // 静态方法返回一个数组,包含给定对象自有的可枚举字符串键属性的键值对。
// const obj = { foo: "bar", baz: 42 };
// console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]
for await...of // 异步迭代器
showDirectoryPickerAPI有兼容要求,如果当前开发的浏览器不支持,建议查询其他解决方案,感兴趣的也看看
实现
<button id="btn">文件夹读取</button>
const btn = document.getElementById("btn");
btn.addEventListener("click", async function (e) {
const handle = await window.showDirectoryPicker();
console.log(handle);
});
通过showDirectoryPickerAPi可以得到一个文件目录,包含名称、文件/文件夹类型,注意方法是异步的,得到一个FileSystemDirectoryHandle处理器
此时我们采用异步迭代器对目录进行处理,得到一个类似Map对象的键值对
<button id="btn">文件夹读取</button>
const btn = document.getElementById("btn");
btn.addEventListener("click", async function (e) {
const handle = await window.showDirectoryPicker();
const ent = await handle.entries();
for await (const item of ent) {
console.log(item);
}
});
将目录处理成一个我们常见的树形数据
<button id="btn">文件夹读取</button>
const btn = document.getElementById("btn");
async function processHandle(handle) {
if (handle.kind === "file") {
// 如果是文件直接退出
return;
}
const ent = await handle.entries();
handle.children = [];
for await (const item of ent) {
handle.children.push(item[1]);
processHandle(item[1]);
}
}
btn.addEventListener("click", async function (e) {
const handle = await window.showDirectoryPicker();
await processHandle(handle);
});
读取文件内容信息,得到我们平时上传的文件对象,然后我们就可以直接读出
<button id="btn">文件夹读取</button>
const btn = document.getElementById("btn");
async function processHandle(handle) {
if (handle.kind === "file") {
// 如果是文件直接退出
return;
}
const ent = await handle.entries();
handle.children = [];
for await (const item of ent) {
handle.children.push(item[1]);
processHandle(item[1]);
}
}
btn.addEventListener("click", async function (e) {
const handle = await window.showDirectoryPicker();
await processHandle(handle);
const file = await handle.children[5].getFile();
const reader = new FileReader();
reader.onload = (e) => {
console.log(e.target.result);
};
console.log(reader.readAsText(file)); // 文件内容
});
结尾
东西都不是啥高级的东西,就是需要平时的积累,创新,本次过后我也认识到,技术在不断的迭代,如果不一直学习,将会差距越来越大,为什么会有35岁危机,个人认为有扎实的功底,不断创新的精神,和不断上进的决心,坚持,在各行各业都不大可能淘汰,企业差的永远是能解决问题的人才。最后祝愿各位兄弟姐妹都能一起在此行业一起走下去。
创作小白,第一次写文章,轻点喷,嘿嘿!代码如有不对,还请在评论区指出,与君共勉之!!!