王一之 发表于 2022-9-15 11:28:17

[油猴脚本开发指南]操作本地文件

经常看见有人提问怎么去下载文件、保存文件之类的问题的,一直是说用(https://developer.mozilla.org/en-US/docs/Web/API/File_System_Access_API#browser_compatibility) 但是怎么用,从没说过,今天来研究一下,顺便写一些示例

使用之前,先注意一下浏览器兼容性Firefox是完全不支持,另外依旧有一些局限性,需要用户手动触发操作

## 获取权限
> window.showOpenFilePicker/showDirectoryPicker
> 这两个API用于打开一个窗口,授权文件/目录,例如下面这样

```js
    async function getFile() {
      // open directory picker
      const dirHandle = await window.showDirectoryPicker();
      console.log(dirHandle);
    }
    getFile();
```
调用后会打开一个窗口,选择允许查看的文件目录~~~~
!(data/attachment/forum/202209/15/103739dzng3pzvcnocgpig.png)
确认授权
!(data/attachment/forum/202209/15/103749sso1xz8v1pqqzsaq.png)
完成后会返回一个下面这样的结构体
!(data/attachment/forum/202209/15/103856zxwsf1s21s8sksw1.png)

但是刷新页面后,会报下面这个错误,必须要有用户操作触发才行(但是不知道为什么第一次是可以的。。。)
```js
Failed to execute 'showDirectoryPicker' on 'Window': Must be handling a user gesture to show a file picker.
```
像这样,在这里我指定来一个参数{mode:"readwrite"},这样就可以获取目录的读写权限,对目录为所欲为
```js
    const button = document.createElement('button');
    button.innerText = "点我授权目录";
    document.body.firstChild.after(button);
    button.addEventListener('click', async function () {
      async function getFile() {
            // open directory picker
            const dirHandle = await window.showDirectoryPicker({mode:"readwrite"});
            console.log(dirHandle);
      }
      getFile();
    });
```
另外我发现返回的dirHandle的对象是可以存到indexedDB(可以存储js 对象)中去的,但是不清楚能不能继续给下次调用,有兴趣的朋友可以试试。

## 读写文件
既然获取到了权限,就来试试能不能操作本地文件,获取到的对象是:(https://developer.mozilla.org/en-US/docs/Web/API/FileSystemDirectoryHandle),更多内容可看MDN
```js
const button2 = document.createElement('button');
    button2.innerText = "点我读取目录&写点东西";
    document.body.firstChild.after(button2);
    button2.addEventListener('click', async function () {
      // 读取目录
      for await (const item of dirHandle.values()) {
            console.log(item)
      }
      // 写文件
      const fileHandle = await dirHandle.getFileHandle("hello-world.txt", { create: true });
      const writable = await fileHandle.createWritable();
      await writable.write("Hello World!");
      await writable.close();
    });
```


## END
简单过了一下FileSystemAPI,感觉还是很强大的,应该能衍生不少玩法

steven026 发表于 2022-9-15 12:23:44

GGNB,试了下只有脚本猫能用?油猴似乎不能用【脚本猫NB
另外建议把自动调用的getFile()删了,好像是这行出了问题,可能一定要用户真实操作才能正常用(类似isTrusted)?

脚本体验师001 发表于 2022-9-15 13:13:48

油猴中文网确实能学到不少东西。。。
然脚本猫一定要去兼容别的脚本管理器?我倒是希望脚本猫出几个炸天的特性。你还只能在脚本猫上使,那就好气人了

脚本体验师001 发表于 2022-9-15 13:29:49

另外我发现返回的dirHandle的对象是可以存到indexedDB(可以存储js 对象)中去的,但是不清楚能不能继续给下次调用,有兴趣的朋友可以试试。
你在暗示什么?

王一之 发表于 2022-9-15 13:45:40

脚本体验师001 发表于 2022-9-15 13:13
油猴中文网确实能学到不少东西。。。
然脚本猫一定要去兼容别的脚本管理器?我倒是希望脚本猫出几个炸天的 ...

有点想不到有什么好特性能出了

王一之 发表于 2022-9-15 13:46:57

脚本体验师001 发表于 2022-9-15 13:29
另外我发现返回的dirHandle的对象是可以存到indexedDB(可以存储js 对象)中去的,但是不清楚能不能继续给 ...

我看vscode web实现的时候 无意间看到这个对象存进了indexeddb,不知道是有什么作用没。可能只是做个记录 用来读取之前打开过的文件夹而已

王一之 发表于 2022-9-15 13:47:33

steven026 发表于 2022-9-15 12:23
GGNB,试了下只有脚本猫能用?油猴似乎不能用【脚本猫NB
另外建议把自动调用的getFile()删了,好像是这行出 ...

这我没注意 我用脚本猫的。应该和实现有关,油猴试试unsafe Window

王一之 发表于 2022-9-15 13:48:17

steven026 发表于 2022-9-15 12:23
GGNB,试了下只有脚本猫能用?油猴似乎不能用【脚本猫NB
另外建议把自动调用的getFile()删了,好像是这行出 ...

第一次调用时getFile有用。。。

steven026 发表于 2022-9-15 13:56:25

王一之 发表于 2022-9-15 13:47
这我没注意 我用脚本猫的。应该和实现有关,油猴试试unsafe Window

油猴好像不声明//@grant none就默认是沙盒环境
然后document可能就指向沙盒环境的window上去了

tfsn20 发表于 2022-9-15 16:01:57

我敲,好东西,以前安卓autojs与浏览器通信我用的将信息写在网页上,让autojs去读取,然后浏览器读取本地文件使用的require js(用autojs写的js文件)
页: [1] 2
查看完整版本: [油猴脚本开发指南]操作本地文件