Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【drawio探秘】保存当前编辑内容为本地文件并持续实时保存最新编辑的内容 #79

Open
Topppy opened this issue Dec 30, 2022 · 0 comments

Comments

@Topppy
Copy link
Owner

Topppy commented Dec 30, 2022

保存为本地文件并持续实时保存最新编辑的内容

可以使用浏览器的FileSystemWritableFileStream来实现

https://developer.mozilla.org/en-US/docs/Web/API/FileSystemWritableFileStream

兼容性很不好:
image

思路:

  1. 首次保存创造了一个FileSystemFileHandle对象:newHandle,提供对该读写文件的能力。
  2. 更新文件内容的时候,通过FileSystemFileHandle创造一个对该文件写入流 :writableStream。
  3. 使用writableStream.write 写入最新的文本Blob,(注意此处是覆盖式的)。
  4. 关闭流
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>file save</title>
    <style>
      #addText {
        width: 400px;
        height: 200px;
      }
    </style>
  </head>
  <body>
    <h1>保存为本地文件并持续实时保存最新编辑的内容</h1>
    <h4>text to save:</h4>
    <div>
      <textarea id="addText" name="addText">hello</textarea>
    </div>
    <button onclick="saveFile()">1. start save</button>
    <button onclick="updateFile()">2. update</button>
    <h4>file contents:</h4>
    <p id="fileContent"></p>
    <script>
      // https://developer.mozilla.org/en-US/docs/Web/API/FileSystemWritableFileStream
      let $textToAdd;
      let $fileContent;
      let newHandle;

      const pickerOpts = {
        types: [
          {
            description: "Text file",
            accept: {
              "text/plain": [".txt"],
            },
          },
        ],
        suggestedName: "testFile",
        excludeAcceptAllOption: true,
        multiple: false,
      };

      async function saveFile() {
        // create a new handle
        console.log("showSaveFilePicker");
        newHandle = await window.showSaveFilePicker(pickerOpts);
        console.log("createWritable");
        // create a FileSystemWritableFileStream to write to
        const writableStream = await newHandle.createWritable();

        updateFile();
      }

      async function getFileContents() {
        const fileData = await newHandle.getFile();
        const res = await fileData.text();
        console.log("fileText: ", res);
        $fileContent.innerText = res;
      }

      async function updateFileContent(text) {
        // create a FileSystemWritableFileStream to write to
        const writableStream = await newHandle.createWritable();

        const data = new Blob([text], { type: "text" });
        // write our file
        await writableStream.write(data);

        // close the file and write the contents to disk.
        await writableStream.close();
      }

      async function updateFile() {
        const text = $textToAdd.value;
        await updateFileContent(text);
        await getFileContents();
      }

      document.addEventListener("DOMContentLoaded", () => {
        $textToAdd = document.getElementById("addText");
        $fileContent = document.getElementById("fileContent");
      });
    </script>
  </body>
</html>

发散一下:可以利用这个特性进行攻击吗?

比如前端通过js改写下载文件的内容。

可以继续研究一下这个API有什么安全限制。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant