我正在尝试设置一个网页,受信任的用户可以上传本地CSV文件,这些文件将被用户解析,验证,审核,然后插入到MySQL数据库的各个表中。
网站的其余部分是使用PHP和jQuery编写的。我知道如何将CSV文件读入PHP并生成查询。问题是文件的验证和解析是交互式的 - 需要向用户询问有关数据的各种信息,将文件中的列与数据库中的字段匹配,并有机会查看和更新回答,直到他们确定一切都是正确的。
每次用户更改内容时,重新加载整个页面似乎都是1990年代,因此我认为AJAX将成为客户端的方式,但似乎浏览器特别禁止打开本地文件“安全理由“。
在将文件实际上传到服务器之前,是否存在一种普遍接受的模式,用于安全有效地让用户根据文件内容做出决策?或者人们真的只是在这种情况下发送了几十个POST请求?
顺便说一下,我们不使用Windows或任何封闭源代码,所以不幸的是该解决方案不能依赖Internet Explorer或ActiveX。
感谢。
答案 0 :(得分:4)
如果您使用从firefox 3.6和Chrome 7开始提供的javascript FileReader API,则无需向服务器发出任何请求。幸运的是,存在非常有趣的文章,可以清楚地解释API的工作原理。
http://www.html5rocks.com/en/tutorials/file/dndfiles/
如果您对不同浏览器中对API的支持有疑虑,请在其他文章的末尾显示:
https://developer.mozilla.org/en/DOM/FileReader
我最近使用此API上传文本和二进制文件,如果您决定尝试并且有任何疑问,请随时与我联系。
答案 1 :(得分:1)
有关如何有效执行此操作的示例,请尝试Papa Parse库。
它可以毫无问题地处理非常大的文件。
答案 2 :(得分:0)
您有两大类解决方案:
可以使用基于标准的实现来完成。最不寻常的选择是依赖于用户复制/粘贴的第二种选择。出于这个原因,大多数实现会选择第一个选项的一些变体。
在哪里放置文件转换的主要逻辑取决于你。如果小心,不需要有任何安全问题。
答案 3 :(得分:0)
HTML:
<form id = "emailform" action = "admincsvupload" role="form" method="post" enctype="multipart/form-data">
<div class="form-group">
<label class="sr-only" for="csvfile">Upload CSV</label>
<input type="file" name = "csvfile" class="form-control" id="csvfile" placeholder="Select CSV file">
</div>
<button type="button" class="btn btn-success" id="btnLoad">Load</button>
<button type="submit" class="btn btn-success" id="btnSubmit" style="display:none">Upload Now!</button>
</form>
0%
Javascript:
// File load as HTMl n a table before actuly upload it on the server
function updateProgress(evt) {
// evt is an ProgressEvent.
if (evt.lengthComputable) {
var percentLoaded = Math.round((evt.loaded / evt.total) * 100);
// Increase the progress bar length.
if (percentLoaded < 100) {
progress.style.width = percentLoaded + '%';
progress.textContent = percentLoaded + '%';
}
}
}
function readBlob(opt_startByte, opt_stopByte) {
var progress = document.querySelector('.percent');
var files = document.getElementById('csvfile').files;
if (!files.length) {
alert('Please select a file!');
return;
}
var file = files[0];
var start = 0;
var stop = file.size - 1;
progress.style.width = '0%';
progress.textContent = '0%';
var reader = new FileReader();
//Reader progress
reader.onprogress = updateProgress;
// If we use onloadend, we need to check the readyState.
reader.onloadend = function (evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
var data = evt.target.result;
var delimiter = ',';
var escape = '\n';
var rows = data.split(escape);
var tbl = document.createElement('table');
tbl.style.width = '100%';
//tbl.setAttribute('border', '1', "green");
tbl.className = "table table-hover table-condensed dataTable";
var tbdy = document.createElement('tbody');
for (index in rows) {
var tr = document.createElement('tr'); // creating new row
var items = rows[index].split(delimiter);
for (itemindex in items) {
var td = "";
if (index == 0) {
td = document.createElement('th');
} else {
td = document.createElement('td');
}
td.appendChild(document.createTextNode(items[itemindex])); // creating new cell
tr.appendChild(td); // add to current tr
}
tbdy.appendChild(tr); // add new row (tr) to table
}
tbl.appendChild(tbdy);
document.getElementById('byte_content').innerHTML=tbl;
}
};
// Progress Loading
reader.onloadstart = function(e) {
document.getElementById('progress_bar').className = 'loading';
};
reader.onload = function(e) {
// Ensure that the progress bar displays 100% at the end.
progress.style.width = '100%';
progress.textContent = '100%';
setTimeout("document.getElementById('progress_bar').className='';", 2000);
}
var blob = file.slice(start, stop + 1);
reader.readAsBinaryString(blob);
document.querySelector('#btnLoad').style.display = "none";
document.getElementById("btnSubmit").style.display = "block";
}
//Change event if user select a new file.
document.querySelector('#csvfile').addEventListener('change', function (evt) {
return readBlob();
}, false);