如何在上传到服务器之前预处理本地CSV文件?

时间:2012-04-04 21:42:38

标签: php javascript user-interaction

我正在尝试设置一个网页,受信任的用户可以上传本地CSV文件,这些文件将被用户解析,验证,审核,然后插入到MySQL数据库的各个表中。

网站的其余部分是使用PHP和jQuery编写的。我知道如何将CSV文件读入PHP并生成查询。问题是文件的验证和解析是交互式的 - 需要向用户询问有关数据的各种信息,将文件中的列与数据库中的字段匹配,并有机会查看和更新回答,直到他们确定一切都是正确的。

每次用户更改内容时,重新加载整个页面似乎都是1990年代,因此我认为AJAX将成为客户端的方式,但似乎浏览器特别禁止打开本地文件“安全理由“。

我的问题是:

在将文件实际上传到服务器之前,是否存在一种普遍接受的模式,用于安全有效地让用户根据文件内容做出决策?或者人们真的只是在这种情况下发送了几十个POST请求?

顺便说一下,我们不使用Windows或任何封闭源代码,所以不幸的是该解决方案不能依赖Internet Explorer或ActiveX。

感谢。

4 个答案:

答案 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)

您有两大类解决方案:

  • 上传CSV并依靠服务器端逻辑执行转换,并可能与用户进行交互。这可能包括加载一个浏览器页面,该页面在上传后实现第二个选择。
  • 让用户将文件复制并粘贴到浏览器文本框中,并使用基于浏览器的javascript或applet转换文本,可能在本地或与网络服务器进行交互。

可以使用基于标准的实现来完成。最不寻常的选择是依赖于用户复制/粘贴的第二种选择。出于这个原因,大多数实现会选择第一个选项的一些变体。

在哪里放置文件转换的主要逻辑取决于你。如果小心,不需要有任何安全问题。

答案 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);