我正在尝试上传和保存多个JSON文件。以前上传和保存一个JSON文件时,我是这样做的:
<input type="file" id="file" ref="fileSelect" class="custom-file-input" @change="showfiles" />
showfiles() {
let files = (this.$refs.fileSelect as HTMLInputElement).files
var reader = new FileReader();
reader.onload = () => { this.data = JSON.parse(reader.result as string); }
reader.readAsText(files![0]);
}
我保存json文件在this.data
现在我想上传和保存多个JSON文件类似,并将它们保存在this.data
所以我更新了上面的代码如下(我认为我可以循环并附加文件数据):
<input multiple type="file" id="file" ref="fileSelect" class="custom-file-input" @change="showfiles" />
showfiles() {
let files = (this.$refs.fileSelect as HTMLInputElement).files
for(let i=0;i<files!.length;i++){
var reader = new FileReader();
reader.onload = () => { this.data[i] = JSON.parse(reader.result as string); }
reader.readAsText(files![i]);}
}
但是这并没有按预期工作,它只是附加了最后选择的文件多次(并且第0个索引是空的,所以例如,如果我在this.data
0 is null and 1,2 index are data from file3.json
中选择file1.json , file2.json, file3.json
。我做错了什么?
我当前的完整代码:
<input multiple type="file" id="file" ref="fileSelect" class="custom-file-input" @change="showfiles" />
<script lang='ts'>
import { defineComponent } from "vue"
export default defineComponent({
name: 'HomeView',
props: [],
data(){
return{
data:{}
};
},
methods: {
showfiles() {
this.data={}
let files = (this.$refs.fileSelect as HTMLInputElement).files
for(let i=0;i<files!.length;i++){
var reader = new FileReader();
reader.onload = () => { this.data[i] = JSON.parse(reader.result as string);}
reader.readAsText(files![i]);
}
}
在你的问题中真的没有什么Vue或TypeScript特定的,所以我将尝试用普通的JavaScript来回答。我已经包含了一个可运行的代码片段。
简而言之,当选定的文件发生变化时:
- 创建单个
FileReader
,而不是每个选定的文件一个。 - 附加单个
load
事件监听器,获取FileReader
的result
(文件内容) - 读取每个文件,一次一个,等待每个文件被加载和读取,然后读取下一个文件。
如果是我,我会编写一个函数来读取文件并解析文件的内容。然后,您可以从showFiles
方法调用该函数,并将每个文件的结果await
。
下面是一个原始JavaScript的可运行示例。注意,inputFile
对应于你的fileSelect
引用,results
数组对应于你的data
数组(顺便说一句,它应该是一个数组而不是一个对象)。此外,我已经在JS代码中连接了change
事件侦听器,但它与模板中的@change
侦听器相同。
(function() {
'use strict'
const inputFile = document.getElementById('inputFile')
// Holds the contents of each selected file.
const results = []
inputFile.addEventListener('change', async e => {
const files = e.target.files
const reader = new FileReader()
// New set of results each time.
results.splice(0)
for (const file of files)
results.push(await readFile(reader, file))
// Do something with the files.
console.log(results)
})
/**
* Read a file asynchronously and resolve with the contents.
*
* @param {FileReader} reader - A FileReader instance that will read `file`
* as text.
* @param {File} file - A selected File instance.
*/
function readFile(reader, file) {
const deferredResult = new Promise(resolve => {
reader.addEventListener('load', function getResult() {
resolve(reader.result)
reader.removeEventListener('load', getResult)
})
})
reader.readAsText(file)
return deferredResult
}
})()
<!doctype html>
<html>
<head>
</head>
<body>
<input multiple type="file" id="inputFile" accept=".json">
</body>
</html>