背景介绍
最近在做一个数据可视化系统,对csv文件中数据进行处理后,以统计图表的形式实现可视化,使用的技术有JavaScript、D3、HTML,代码中有csv、js、html三个文件夹。
由于D3提供了csv文件读取函数——d3.csv(),本想在js文件中直接使用,但在本地直接运行html文件的时候报出以下两个错误:
Access to XMLHttpRequest at ‘file://’ from origin ‘null’ has been
blocked by CORS policy: Cross origin requests are only supported for
protocol schemes: http, data, chrome-extension, edge, https,
chrome-untrusted.
Failed to load resource: net::ERR_FAILED
分析
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing),它允许浏览器向跨源服务器发出XMLHttpRequest请求。
由于CORS不支持file协议方案,所以前端跨域失败,导致加载csv文件内容失败,因而报错;也有说法是因为安全机制禁止了CORS,不允许直接读取本地文件。
解决方法为避免无效跨域。
解决方法:
一、安装Live Server插件
在Visual Studio Code环境下安装Live Server插件,右键单击html文件,选择Open With Live Server运行。
该插件可以强制使文件处在同一个服务器下,避免出现跨域。如图所示:
二、安装npm
安装npm,设置一个webserver来server我们的数据。
参考链接:
D3.js加载csv数据https://www.cnblogs.com/shuaiwang/p/4608378.html
npm安装教程https://www.cnblogs.com/lgx5/p/10732016.html
三、使用input标签
使用HTML的input标签导入csv文件,通过loadData.js对文件进行处理后再传递给其他js文件。
流程为:读取文件夹内的所有文件;将csv文件转为数组形式;声明一个数组保存所有文件内容;使用数据。
html文件部分代码如下:
<div>
<input type="file" id="readCsvFile" onchange="fileImport()"
style="position: absolute;left: 46%;top:54%;width:200px;"
webkitdirectory/>
<!--webkitdirectory实现文件夹上传-->
</div>
loadData.js文件代码如下:
//存储由csv文件转变成的数组
filesData=[];
function fileImport() {
//获取读取本地文件的File对象
var selectedFiles = document.getElementById('readCsvFile').files;//把document.getElementById('file')看成是Dom对象.
for (var file of selectedFiles) {
var reader = new FileReader(); //这是核心,读取操作由它完成.
reader.readAsText(file); //读取文件的内容
reader.onload = function () {
//当读取完成后回调这个函数,然后此时文件的内容存储到了result中,直接操作即可
//将csv内容由文本形式转为数组形式;需要确保csv文件最后一行不为空。
var lines = this.result.split('\r\n');
var titles = lines[0].split(",");
var data = new Array(lines.length - 1);
for (var i = 1; i < lines.length; i++) {
data[i - 1] = {};
lines[i] = lines[i].split(",");
for (var j = 0; j < titles.length; j++) {
data[i - 1][titles[j]] = lines[i][j];
}
}
//data为处理后的数组
filesData.push(data);
//console.log(filesData);
//使用csv文件的数据
if (filesData.length >= 3) {
useRadarData(filesData[1]);//有时要注意数据使用顺序
useMatrixData(filesData[2]);
useBarChartData(filesData[0]);
}
}
}//for,selectedFiles
}
以上。