浏览器读写文件,保存文件后,再用FileReader读取文件onload回调不执行

我想做这么一件事,让用户选中一个文本文件,用户确认之后,可以自由对用户选择的文本文件进行读写。

为了简单测试,基于vue的ui库框架此编写了如下代码,只把js代码部分贴出来



<script>
export default {
  data() {
    return {
     
      save_text: "",
      read_text: "",
      file: undefined,
      fileHandle: undefined,
    };
  },
  created() {},
  methods: {

    //选择文件的方法
    async chooseFile() {
      var [fileHandle] = await window.showOpenFilePicker();

      var permission = await fileHandle.queryPermission();
      //   console.log(permission);

      //获取文件
      const file = await fileHandle.getFile();
      // console.log(file);

      //判断文件类型
      if (fileHandle.kind === "file") {
        //console.log("this is file");
        this.file = file;
        this.fileHandle = fileHandle;
      } else if (fileHandle.kind === "directory") {
        //console.log("this is directory");
        return;
      }
    },

    //保存文件的方法
    async saveFile() {
      var writeContent = this.save_text;
      if (this.fileHandle == undefined) {
        this.$message.error("无法执行,请打开要保存的文件");
        return;
      }
      var fileHandle = this.fileHandle;

      //创建写文件内容
      const writable = await fileHandle.createWritable();

      //写入内容到文件
      await writable.write(writeContent + ":" + new Date().getTime());
      //关闭写入操作,否则内容不会写入到文件
      await writable.close();
    },

    //读取文件的方法
    async readFile() {
      if (this.file == undefined) {
        this.$message.error("无法执行,请打开要读取的文件");
        return;
      }
      var file = this.file;

      
      var reader = new FileReader();
      var successFunc = this.readFileSuccess;
      reader.onloadend = (e) => {
        console.log(reader.result);
      };
      reader.onload = function () {
        successFunc(this.result);
      };

      reader.readAsText(file);
    },
    
    readFileSuccess(result) {
      console.log("reuslt:" + result);
      this.read_text = result;
    },
  },
};
</script>

通过chooseFile方法弹出文件选择对话框,让用户选择文件,用户选择一个文件后,可以点击“读取”按钮,点击事件调用readFile方法读取文件了。然后点击“保存”按钮触发点击事件调用saveFile方法,保存文件。

问题出在调用saveFile方法保存文件后,再去调用readFile方法读取文件,会发现onload回调不触发,onloadend回调会触发,但是起reader.result的内容是null值,需要在重新调用文件选择方法chooseFile,选择文件,在调用readFile方法,才能触发onload方法读取到文件的内容。

我想要通过浏览器调用api反复读写用户确定提交要读写的文件,但对于指定的单个文件的操作,只要用户选择确认提交要修改的文件后,不想反复调用文件选择对话框的方法来解决,这个要怎么解决?

阅读 2k
1 个回答

太长的代码除非逻辑清晰、注释得当,不然别人看起来会很吃力。

如果你是想单纯实现加粗字体描述的“一次选择,多次读写”的话,最好是在第一次 readAsText 之后,保留读取的结果,后续的“读”都是“读”这个结果(当然也可以允许用户覆盖)。
因为按照标准, JS 在网页里对文件的读写只有两种:

  • 用户选择;
  • 下载文件。

这意味着真正意义上的“反复读写”是不可能的(Chrome 支持,但是 FireFox 不支持,还有你这里使用的一些 API 也是 FireFox 不支持的)。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题