Как предварительно обработать локальный файл CSV перед загрузкой на сервер?

Я пытаюсь создать веб-страницу, где доверенные пользователи могут загружать локальные файлы CSV, которые будут анализироваться, проверяться, проверяться пользователями и затем вставляться в различные таблицы в базе данных MySQL.

Остальная часть сайта написана с использованием PHP и jQuery. Я знаю, как читать CSV-файл в PHP и генерировать запрос. Проблема в том, что проверка и синтаксический анализ файла интерактивны – пользователю необходимо получить различную информацию о данных, сопоставить столбцы с файлом с полями в базе данных и получить возможность просмотреть и обновить их пока они не уверены, что все правильно.

Кажется, что 1990-е годы перезагружают всю страницу каждый раз, когда пользователь что-то меняет, поэтому я предположил, что AJAX будет способом сделать это на стороне клиента, но кажется, что открытие локальных файлов специально предотвращено браузерами для «соображений безопасности», ,

Мой вопрос:

Существует ли общепринятый шаблон для безопасного и эффективного разрешения пользователю принимать решения на основе содержимого файла перед фактической загрузкой файла на сервер? Или люди действительно просто отправляют десятки запросов POST в таких ситуациях?

Кстати, мы не используем Windows или что-то закрытое, поэтому, к сожалению, решение не может полагаться на Internet Explorer или ActiveX.

Благодарю.

Вам не нужно делать какие-либо запросы на сервер, если вы используете API-интерфейс javascript FileReader, доступный начиная с firefox 3.6 и Chrome 7. К счастью, существуют действительно интересные статьи, которые достаточно четко объясняют, как работает API.

http://www.html5rocks.com/en/tutorials/file/dndfiles/

Если у вас есть сомнения по поводу поддержки API в разных браузерах, он отображается в конце этой другой статьи:

https://developer.mozilla.org/en/DOM/FileReader

Я недавно использовал этот API для загрузки как текстовых, так и двоичных файлов, поэтому не стесняйтесь возвращаться ко мне, если вы решите, что хотите попробовать, и у вас есть какие-то сомнения.

Для примера того, как это сделать эффективно, попробуйте библиотеку Papa Parse .

Он может обрабатывать очень большие файлы без проблем.

У вас есть два широких класса решений:

  • Загрузите CSV и полагайтесь на логику на стороне сервера для выполнения преобразований и, возможно, взаимодействуйте с пользователем. Это может включать загрузку страницы браузера, которая реализует второй вариант после загрузки.
  • Попросите пользователя скопировать и вставить файл в текстовое поле браузера и использовать браузер javascript или апплеты, чтобы преобразовать текст, возможно, взаимодействуя локально или с веб-сервером.

Любой из них может быть реализован на основе стандартов. Самым необычным вариантом является второй выбор, основанный на копировании / вставке пользователя. По этой причине большинство реализаций выбирают некоторые варианты первого варианта.

Где поставить основную логику преобразования файлов зависит от вас. Там не должно быть никаких проблем с безопасностью, если будет предпринята забота.

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 na 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);