Yukiniro

Yukiniro

Change the world.

在瀏覽器中進行文件操作#

在開發 WebApp 時可能會遇到文件相關的操作,比如上傳文件到伺服器、下載文件到本地、快取文件等,下面會介紹幾種不同的方式進行文件操作。

基於標籤的上傳和下載#

最常用的文件上傳方式應該是使用 input 標籤,通過設置 input 標籤的 type=”file” 可以允許用戶從本地選擇文件進行上傳。

function InputFile() {
	const [file, setFile] = useState<File | null>(null);
	const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;
    setFile(file);
  };
	return <input onChange={handleChange} type="file" />
}

文件訪問 API#

文件系統訪問 API(File System Access API)屬於文件系統 API 的一部分,可以通過使用 API 在用戶的操作下完成文件的讀寫。

在使用該 API 進行文件操作時會使用以下接口

  • showOpenFilePicker:用於顯示一個文件選擇器並允許用戶選擇一個或多個文件,然後返回這些文件的句柄;
export function PickerFS() {
	const [file, setFile] = useState<File | null>(null);
	const handleChooseFile = async () => {
    const fileHandles = await window.showOpenFilePicker();
    const file = await fileHandles[0].getFile();
    setFile(file);
  };
  return <Button onClick={handleChooseFile}>Click</Button>
}
  • showSaveFilePicker:用於顯示一個文件選擇器並允許用戶保存一個文件(覆蓋或者新建);
export function PickerFS() {
	const handleChooseFile = async () => {
    const directoryHandle = await window.showDirectoryPicker();
    const keys = directoryHandle.keys();
    // 打印該目錄下所有文件的名字
    for await (const key of keys) {
      console.log(key);
    }
  };
  return <Button onClick={handleChooseFile}>Click</Button>
}
export function PickerFS() {
	const [file, setFile] = useState<File | null>(null);
	const handleDownloadFile= async () => {
    const opts = {
      suggestedName: "test.txt",
      types: [
        {
          description: "Text file",
          accept: { "text/plain": [".txt"] },
        },
      ],
    };

    const fileHandle = await window.showSaveFilePicker(opts);
    const writable = await fileHandle.createWritable();
    await writable.write("Hello, world!");
    await writable.close();
  };
  return <Button onClick={handleDownloadFile}>Click</Button>
}

源私有文件系統#

源私有文件系統跟上面的文件訪問系統類似,都是文件系統 API 的一部分,但是它們有個最直接的差異就是是否對用戶可見。showXXX 接口都需要打開文件(目錄)選擇器,並且需要用戶主動選擇文件(目錄),保存的文件也是需要保存到用戶指定的路徑,但是源私有文件系統的交互不會對用戶可見,並且保存的文件是經過處理的數據,用戶無法看到原始數據。

export function OpFs() {
  const handleChooseFile = async (event: React.ChangeEvent<HTMLInputElement>) => {
    const fileList = event.target.files;
    const file = fileList && fileList[0];
    if (!file) return;

    const opfsRoot = await navigator.storage.getDirectory();
    const fileHandle = await opfsRoot.getFileHandle(file.name, { create: true });
    const writable = await fileHandle.createWritable();
    await writable.write(file);
    await writable.close();
  };

  return <InputFile onChange={handleChooseFile} />;
}

await navigator.storage.getDirectory() 返回一個表示用戶本地文件系統根目錄的文件句柄,然後通過 getFileHandle 獲取指定文件的句柄,create 為 true 表示如果沒有該文件的話就會創建一個,接著使用 createWritable 創建可寫流,開發者可以通過這個可寫流向指定文件寫入數據,最後關閉可寫流。

注意事項#

參見#

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。