DAY21 - 网页可以操作电脑里的档案?!本地端档案覆写 - The File System Access API

其实也是某天收到这个需求,一开始觉得怎麽可能,网页要存我电脑的档案!什麽情境才会用到这个功能...还真的有,当你的网页是一个编辑工具,储存可以存到自己的电脑,也可以把电脑的档案开启在编辑器编辑,编一编之後又可以回存回去~ 是不是!很亲民的需求XD

今天我们要来介绍的就是可以帮助我们在浏览器上存取本机档案的The File System Access API

The File System Access API

前身其实称作Native File System API,更早之前也称作Writeable Files API。The File System Access可以让web可以直接存取、修改使用者装置里面的档案。

应用场景

通常是会用在开发在web的编辑器时,EX:图片编辑器,在线上调整图档颜色、滤镜等等,存到装置後,又想在对图档修改,再回存。文字编辑器的范例应用可以参考这个连结

浏览器支援度

目前支援度其实蛮少的只支援chrome, edge, opera

重点物件介绍

档案物件:FileSystemFileHandle

透过window.showOpenFilePicker选取档案後取得的物件

  • getFile: 从FileSystemFileHandle取得file物件
  • createWritable: 要让档案物件成为可写入需呼叫
    //writable可透过write覆写内容至档案,写完之後呼叫close关闭writable状态
    writable.write(contents);
    writable.close();
    

方法:showOpenFilePicker 选择档案

打开file manager,让使用者选取档案

方法:showSaveFilePicker 储存档案

打开file manager,让使用者选取位置後,储存档案

功能介绍

以下程序皆以vue.js为例

应用01. showOpenFilePicker打开file manager让使用者选取档案

注意,这边是「不需透过input type="file"」,可以再任意的元素上ex.button上开启file manager

UI画面

  • 点选按钮
  • 开启file manager

程序

<div class="section-save">
    <p>模拟1: 开启档案</p>
    <button @click="openFileNew">Open</button>
</div>
async openFileNew(){
  let fileHandle;
  [fileHandle] = await window.showOpenFilePicker();
  //FileSystemFileHandle物件
  const file = await fileHandle.getFile(); // file物件
  console.log('file',file);
},
  1. 透过showOpenFilePicke打开file manger,选取的档案为FileSysteFileHandle物件
  2. FileSysteFileHandle物件透过getFile()就可取得当中的file物件,便可使用之前file物件的处理方式

应用02. showSaveFilePicker writeFile 选定位置,另存新档後,修改後可直接存至原档

UI画面

  • 点选save to local按钮
  • 透过showSaveFilePicker打开save file的视窗
  • 按储存後会再选择的位置存挡
  • 修改输入框的文字内容,会直接回存到刚刚的example.zip

程序

<div class="section-save">
    <p>模拟2: 第一次存新档案,後续存回原档</p>
    <input type="text" v-model="textContent">
    <button @click="saveNew">save to local</button>
</div>
/***
 * 存档
 ***/
async saveNew(){
    const _self = this;
    console.log('save new', this.saveNew);
    let zip = new JSZip(); // 建立jszip物件 准备打包
    zip.file('test.txt', this.textContent); //将文件档案放到zip中
    //第一次存档 选择位置存zip
    if(_self.isSaveFirstTime){
        let options = {
            suggestedName: 'example.zip', //给予存档预设名字
            types:[{
                accept: {
                  'application/zip': ['.zip'], //建议zip格式
                },
            }]
        }
        this.targetFileObject = await window.showSaveFilePicker(options); //储存时
        console.log('handle',this.targetFileObject); //FileSystemFileHandle
        _self.isSaveFirstTime = false;
    }

    zip.generateAsync({type: 'blob'}).then(async (content)=>{
        // 写进档案中
        await _self.writeFile(this.targetFileObject, content)
        _self.isSaveFirstTime = false;
    })


},
/***写入本地端档案 
 * fileHandle: 需为FileSystemFileHandle物件
 * contents: 要被写入的内容
 ***/
async writeFile(fileHandle, contents) {
console.log("===== Write File Start =====");
//如果已经建立过createWritable,则直接覆写
if (fileHandle.createWriter) {
    const writer = await fileHandle.createWriter();  // createWriter
    await writer.write(0, contents);
    await writer.close();
    return;
}
//为建立过createWritable,建立後覆写
const writable = await fileHandle.createWritable(); // createWritable
await writable.write(contents);
await writable.close();
console.log("===== Write File End =====");
},
  • jsZip和saveAs的用法可以参考昨天的文章喔XD

附上实际的程序档案,给大家玩玩 [连结]


常见错误分享

在专案开发时,写到存档至地端时曾经发生以下错误:

failed to execute 'showSaveFilePicker' on 'Window': Must be handling a user gesture to show a file picker.

错误原因

这个错误是因为,有的时候要被储存的档案处理时间比较久,还正在处理的同时我们也呼叫的showSaveFilePicker的视窗,才会有这个错误。

解决办法

建议顺序可以调整成:先把存挡的位置处理好後,再去做档案相关的处理。就确保不会有档案还在处理又要乎呼叫showSaveFilePicker的状况。
意即 showSaveFilePicker选完储存位置 -> 档案资料处理


唠叨废话time可跳过~~~
终於~~~ 档案处理应该是最後一天分享了,
可能还有很多需要改进跟讲得更清楚,不过因为还有别的主题还想写,
就先把我自己很基础的认知跟觉得很常见的应用,在这几天介绍给他~~
明天工作上有重要的事等等要去努力一下,今天就到这边罗,希望明天顺利RRR


Ref


<<:  Day 24 开发者福音无服务器运算

>>:  #21 No-code 之旅 — 如何让网站在分享时看起来漂亮和有吸引力?Open Graph (OG) 简介

Golang 转生到web世界

Golang 因为对於web比较熟的关系,还是希望使用golang来做点web相关的事情,如果是写p...

HERE mSDK - Map Rendering

作为一个地图SDK,最基础最重要的功能首先是地图呈现, 那麽今天我们仍然以 HERE mSDK (P...

Day9:卷积神经网路(Convolutional Neural Networks,CNN)介绍

  卷积神经网路(Convolutional Neural Networks,以下称CNN)在图片和...

Day25- Go with MySQL

前言 做为一个後端工程师,在架设网站时,免不了碰到资料上的问题,可能在顾客交易後,需要存取订单,以保...