上传和解析多个JSON文件在javascript和vuejs



我正在尝试上传和保存多个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.data0 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事件监听器,获取FileReaderresult(文件内容)
  • 读取每个文件,一次一个,等待每个文件被加载和读取,然后读取下一个文件。

如果是我,我会编写一个函数来读取文件并解析文件的内容。然后,您可以从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>

最新更新