我想做这么一件事,让用户选中一个文本文件,用户确认之后,可以自由对用户选择的文本文件进行读写。
为了简单测试,基于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反复读写用户确定提交要读写的文件,但对于指定的单个文件的操作,只要用户选择确认提交要修改的文件后,不想反复调用文件选择对话框的方法来解决,这个要怎么解决?
太长的代码除非逻辑清晰、注释得当,不然别人看起来会很吃力。
如果你是想单纯实现加粗字体描述的“一次选择,多次读写”的话,最好是在第一次
readAsText
之后,保留读取的结果,后续的“读”都是“读”这个结果(当然也可以允许用户覆盖)。因为按照标准, JS 在网页里对文件的读写只有两种:
这意味着真正意义上的“反复读写”是不可能的(Chrome 支持,但是 FireFox 不支持,还有你这里使用的一些 API 也是 FireFox 不支持的)。