У меня есть форма загрузки, где пользователи могут загружать файлы. После завершения загрузки файлы обрабатываются по почте, и иногда обработка занимает 10-15 секунд после завершения загрузки.
После того, как загрузка завершена, индикатор выполнения находится на уровне 100%, но как можно определить, когда файл был завершен, чтобы вы могли показать пользователю знак «подождите», пока файл обрабатывается. Пользователь может подумать, что браузер заморозил и разбился, поскольку индикатор выполнения находится на уровне 100%, но ничего не происходит.
Предпочтительным является клиентское решение в чистом HTML5 + javascript, но не обязательно 🙂
Пытаться
HTML
<progress min="0" max="10000"></progress> <output for="progress"></output> <output for="progress"></output> <br /> <table id="results"></table>
JS
var len = arr.length // file length , start = 0 // update progress , outputs = $("output[for=progress]") // notifications , progress = $("progress") , results = $("#results") // post processing // gif spinner , spinner = $("<img />", { "src": "data:image/gif;charset=binary;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAKAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQACgABACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkEAAoAAgAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkEAAoAAwAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkEAAoABAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQACgAFACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQACgAGACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAAKAAcALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==" }); // upload file var request = function () { progress.prop("max", len); s = setInterval(function () { progress.prop("value", ++start); outputs.eq(0) .text("uploading file...") }, 1) return $.post("/echo/json/", { json: JSON.stringify(arr) }) .then(function (data) { clearInterval(s) s = null; progress.prop("value", len); outputs.eq(0) .html("upload complete ! <br />processing response, please wait...") .next(outputs.eq(1)) .html(spinner); return data }) }; request() .then(function (data) { // do post upload processing stuff var process = function() { var dfd = new $.Deferred(); // processing... t = setTimeout(function () { data.forEach(function (res) { results.append( $("<tr />", { "html": $("<td />", { "html": res.value }) })) }); if (results.find("tr").length === len) { dfd.resolve("complete !") } }, 1 + Math.floor(Math.random() * 15000)); return dfd.promise() }; // do stuff when all post processing complete process().then(function(complete) { outputs.eq(0).empty() .next(outputs.eq(1)) .html(complete); clearTimeout(t); t = null; }) });
Поскольку у вас есть индикатор выполнения, чтобы показать процесс формы. Чтобы добавить больше деталей во время обработки, вы можете добавить изображение, подобное приведенному ниже.
Он покажет пользователю, что ваша форма все еще находится на процессе, создайте свой собственный образ здесь.
Это может помочь пользователю – браузер не замерз.
Для этого я использую пользовательский виджет загрузки. На стороне сервера я отправляю следующую информацию клиенту, когда он запрашивает обновление: Процент полученного файла плюс сообщение о состоянии. Через сообщение я могу дать дополнительную обратную связь, например, какой этап обработки сообщения происходит или отображать ошибки.
Я использую плагин jquery под названием pekeupload. Он мал и легко реализуется и настраивается
http://plugins.jquery.com/pekeUpload/ https://github.com/pekebyte/pekeUpload
Я надеюсь, что это поможет вам
Лучший
Javascript
function initialize_progress(element) { //initializations! $(element).hide(); $(element).find('.progress-bar').prop('style','width: 0'); } function getProgress(process_id){ var re=new RegExp(process_id+"=[^;]+", "i") //construct RE to search for target name/value pair if (document.cookie.match(re)) //if cookie found return document.cookie.match(re)[0].split("=")[1] //return its value return null } function updateProgress(process_id, element){ var percentage, message, name, failed; $(element).show(); var myIntervalID = setInterval(function() { percentage = getProgress(process_id+"_percentage"); name = getProgress(process_id+"_process_name"); message = getProgress(process_id+"_message"); failed = getProgress(process_id+"_process_failed"); if(percentage) $(element).find('.progress-bar').css('width',percentage+'%').html(percentage+"% "+message); },2000); } //initialize progress bar //initialize_progress(".progress"); $(".upload-button").click(function() { //set listener updateProgress('upload_the_pix', ".progress") var request = $.get( "http://example.com/?progress", function(data) { alert(data); }) .done(function() { alert( "second success" ) }).fail(function() { alert( "error" ); }).always(function() { alert( "finished" ); }); });
HTML
<div class="progress"> <div class="progress-bar progress-bar-success progress-bar-striped active" role="progressbar" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style="width: 0%"> </div> </div>
Процесс на стороне сервера – использование PHP
class ProcessProgress { protected static $process_id; //current process_id protected static $process_name; //current process name protected static $debug_mode = false; protected static $process_killed = false; /** * Make settings for process setup * @param $settings * Example: * $settings=array( * 'process_id' => 'upload_photos' //must be provided 'process_name' =>'Database Wipe', //tile of this process ); */ public static function settings($settings) { # process id must be set #make array keys properties if( is_array($settings) ){ foreach($settings as $key => $value){ self::$$key = $value; } } if(self::$debug_mode && !self::$process_id) exit('process_id must me provided in settings array'); if(isset($_COOKIE[self::$process_id."_percentage"])){ unset($_COOKIE[self::$process_id."_percentage"]); unset($_COOKIE[self::$process_id."_message"]); unset($_COOKIE[self::$process_id."_process_name"]); unset($_COOKIE[self::$process_id."_process_complete"]); unset($_COOKIE[self::$process_id."_process_failed"]); unset($_COOKIE[self::$process_id."_process_killed"]); } } /** * Kill this process */ public static function kill() { self::$process_killed = true; } /** * @param $percentage * @param $message * @param bool $complete * @param bool $failed * @return bool */ public function setProgress($percentage, $message, $complete=false, $failed=false){ $process_data = array( 'percentage'=>$percentage, 'message' => $message, 'process_id' => self::$process_id, 'process_name' => self::$process_name, 'process_complete' => $complete, 'process_failed' => $failed, 'process_killed' => self::$process_killed, ); setcookie(self::$process_id."_percentage", $percentage, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_message", $message, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_name", self::$process_name, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_complete", $complete, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_failed", $failed, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_killed", self::$process_killed, time() + (86400 * 30)); // 86400 = 1 day //verify if(isset($_COOKIE[self::$process_id])) return true; #delay 1 second //sleep(1); } }
сclass ProcessProgress { protected static $process_id; //current process_id protected static $process_name; //current process name protected static $debug_mode = false; protected static $process_killed = false; /** * Make settings for process setup * @param $settings * Example: * $settings=array( * 'process_id' => 'upload_photos' //must be provided 'process_name' =>'Database Wipe', //tile of this process ); */ public static function settings($settings) { # process id must be set #make array keys properties if( is_array($settings) ){ foreach($settings as $key => $value){ self::$$key = $value; } } if(self::$debug_mode && !self::$process_id) exit('process_id must me provided in settings array'); if(isset($_COOKIE[self::$process_id."_percentage"])){ unset($_COOKIE[self::$process_id."_percentage"]); unset($_COOKIE[self::$process_id."_message"]); unset($_COOKIE[self::$process_id."_process_name"]); unset($_COOKIE[self::$process_id."_process_complete"]); unset($_COOKIE[self::$process_id."_process_failed"]); unset($_COOKIE[self::$process_id."_process_killed"]); } } /** * Kill this process */ public static function kill() { self::$process_killed = true; } /** * @param $percentage * @param $message * @param bool $complete * @param bool $failed * @return bool */ public function setProgress($percentage, $message, $complete=false, $failed=false){ $process_data = array( 'percentage'=>$percentage, 'message' => $message, 'process_id' => self::$process_id, 'process_name' => self::$process_name, 'process_complete' => $complete, 'process_failed' => $failed, 'process_killed' => self::$process_killed, ); setcookie(self::$process_id."_percentage", $percentage, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_message", $message, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_name", self::$process_name, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_complete", $complete, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_failed", $failed, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_killed", self::$process_killed, time() + (86400 * 30)); // 86400 = 1 day //verify if(isset($_COOKIE[self::$process_id])) return true; #delay 1 second //sleep(1); } }
сclass ProcessProgress { protected static $process_id; //current process_id protected static $process_name; //current process name protected static $debug_mode = false; protected static $process_killed = false; /** * Make settings for process setup * @param $settings * Example: * $settings=array( * 'process_id' => 'upload_photos' //must be provided 'process_name' =>'Database Wipe', //tile of this process ); */ public static function settings($settings) { # process id must be set #make array keys properties if( is_array($settings) ){ foreach($settings as $key => $value){ self::$$key = $value; } } if(self::$debug_mode && !self::$process_id) exit('process_id must me provided in settings array'); if(isset($_COOKIE[self::$process_id."_percentage"])){ unset($_COOKIE[self::$process_id."_percentage"]); unset($_COOKIE[self::$process_id."_message"]); unset($_COOKIE[self::$process_id."_process_name"]); unset($_COOKIE[self::$process_id."_process_complete"]); unset($_COOKIE[self::$process_id."_process_failed"]); unset($_COOKIE[self::$process_id."_process_killed"]); } } /** * Kill this process */ public static function kill() { self::$process_killed = true; } /** * @param $percentage * @param $message * @param bool $complete * @param bool $failed * @return bool */ public function setProgress($percentage, $message, $complete=false, $failed=false){ $process_data = array( 'percentage'=>$percentage, 'message' => $message, 'process_id' => self::$process_id, 'process_name' => self::$process_name, 'process_complete' => $complete, 'process_failed' => $failed, 'process_killed' => self::$process_killed, ); setcookie(self::$process_id."_percentage", $percentage, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_message", $message, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_name", self::$process_name, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_complete", $complete, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_failed", $failed, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_killed", self::$process_killed, time() + (86400 * 30)); // 86400 = 1 day //verify if(isset($_COOKIE[self::$process_id])) return true; #delay 1 second //sleep(1); } }
сclass ProcessProgress { protected static $process_id; //current process_id protected static $process_name; //current process name protected static $debug_mode = false; protected static $process_killed = false; /** * Make settings for process setup * @param $settings * Example: * $settings=array( * 'process_id' => 'upload_photos' //must be provided 'process_name' =>'Database Wipe', //tile of this process ); */ public static function settings($settings) { # process id must be set #make array keys properties if( is_array($settings) ){ foreach($settings as $key => $value){ self::$$key = $value; } } if(self::$debug_mode && !self::$process_id) exit('process_id must me provided in settings array'); if(isset($_COOKIE[self::$process_id."_percentage"])){ unset($_COOKIE[self::$process_id."_percentage"]); unset($_COOKIE[self::$process_id."_message"]); unset($_COOKIE[self::$process_id."_process_name"]); unset($_COOKIE[self::$process_id."_process_complete"]); unset($_COOKIE[self::$process_id."_process_failed"]); unset($_COOKIE[self::$process_id."_process_killed"]); } } /** * Kill this process */ public static function kill() { self::$process_killed = true; } /** * @param $percentage * @param $message * @param bool $complete * @param bool $failed * @return bool */ public function setProgress($percentage, $message, $complete=false, $failed=false){ $process_data = array( 'percentage'=>$percentage, 'message' => $message, 'process_id' => self::$process_id, 'process_name' => self::$process_name, 'process_complete' => $complete, 'process_failed' => $failed, 'process_killed' => self::$process_killed, ); setcookie(self::$process_id."_percentage", $percentage, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_message", $message, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_name", self::$process_name, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_complete", $complete, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_failed", $failed, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_killed", self::$process_killed, time() + (86400 * 30)); // 86400 = 1 day //verify if(isset($_COOKIE[self::$process_id])) return true; #delay 1 second //sleep(1); } }
сclass ProcessProgress { protected static $process_id; //current process_id protected static $process_name; //current process name protected static $debug_mode = false; protected static $process_killed = false; /** * Make settings for process setup * @param $settings * Example: * $settings=array( * 'process_id' => 'upload_photos' //must be provided 'process_name' =>'Database Wipe', //tile of this process ); */ public static function settings($settings) { # process id must be set #make array keys properties if( is_array($settings) ){ foreach($settings as $key => $value){ self::$$key = $value; } } if(self::$debug_mode && !self::$process_id) exit('process_id must me provided in settings array'); if(isset($_COOKIE[self::$process_id."_percentage"])){ unset($_COOKIE[self::$process_id."_percentage"]); unset($_COOKIE[self::$process_id."_message"]); unset($_COOKIE[self::$process_id."_process_name"]); unset($_COOKIE[self::$process_id."_process_complete"]); unset($_COOKIE[self::$process_id."_process_failed"]); unset($_COOKIE[self::$process_id."_process_killed"]); } } /** * Kill this process */ public static function kill() { self::$process_killed = true; } /** * @param $percentage * @param $message * @param bool $complete * @param bool $failed * @return bool */ public function setProgress($percentage, $message, $complete=false, $failed=false){ $process_data = array( 'percentage'=>$percentage, 'message' => $message, 'process_id' => self::$process_id, 'process_name' => self::$process_name, 'process_complete' => $complete, 'process_failed' => $failed, 'process_killed' => self::$process_killed, ); setcookie(self::$process_id."_percentage", $percentage, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_message", $message, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_name", self::$process_name, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_complete", $complete, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_failed", $failed, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_killed", self::$process_killed, time() + (86400 * 30)); // 86400 = 1 day //verify if(isset($_COOKIE[self::$process_id])) return true; #delay 1 second //sleep(1); } }
сclass ProcessProgress { protected static $process_id; //current process_id protected static $process_name; //current process name protected static $debug_mode = false; protected static $process_killed = false; /** * Make settings for process setup * @param $settings * Example: * $settings=array( * 'process_id' => 'upload_photos' //must be provided 'process_name' =>'Database Wipe', //tile of this process ); */ public static function settings($settings) { # process id must be set #make array keys properties if( is_array($settings) ){ foreach($settings as $key => $value){ self::$$key = $value; } } if(self::$debug_mode && !self::$process_id) exit('process_id must me provided in settings array'); if(isset($_COOKIE[self::$process_id."_percentage"])){ unset($_COOKIE[self::$process_id."_percentage"]); unset($_COOKIE[self::$process_id."_message"]); unset($_COOKIE[self::$process_id."_process_name"]); unset($_COOKIE[self::$process_id."_process_complete"]); unset($_COOKIE[self::$process_id."_process_failed"]); unset($_COOKIE[self::$process_id."_process_killed"]); } } /** * Kill this process */ public static function kill() { self::$process_killed = true; } /** * @param $percentage * @param $message * @param bool $complete * @param bool $failed * @return bool */ public function setProgress($percentage, $message, $complete=false, $failed=false){ $process_data = array( 'percentage'=>$percentage, 'message' => $message, 'process_id' => self::$process_id, 'process_name' => self::$process_name, 'process_complete' => $complete, 'process_failed' => $failed, 'process_killed' => self::$process_killed, ); setcookie(self::$process_id."_percentage", $percentage, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_message", $message, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_name", self::$process_name, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_complete", $complete, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_failed", $failed, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_killed", self::$process_killed, time() + (86400 * 30)); // 86400 = 1 day //verify if(isset($_COOKIE[self::$process_id])) return true; #delay 1 second //sleep(1); } }
сclass ProcessProgress { protected static $process_id; //current process_id protected static $process_name; //current process name protected static $debug_mode = false; protected static $process_killed = false; /** * Make settings for process setup * @param $settings * Example: * $settings=array( * 'process_id' => 'upload_photos' //must be provided 'process_name' =>'Database Wipe', //tile of this process ); */ public static function settings($settings) { # process id must be set #make array keys properties if( is_array($settings) ){ foreach($settings as $key => $value){ self::$$key = $value; } } if(self::$debug_mode && !self::$process_id) exit('process_id must me provided in settings array'); if(isset($_COOKIE[self::$process_id."_percentage"])){ unset($_COOKIE[self::$process_id."_percentage"]); unset($_COOKIE[self::$process_id."_message"]); unset($_COOKIE[self::$process_id."_process_name"]); unset($_COOKIE[self::$process_id."_process_complete"]); unset($_COOKIE[self::$process_id."_process_failed"]); unset($_COOKIE[self::$process_id."_process_killed"]); } } /** * Kill this process */ public static function kill() { self::$process_killed = true; } /** * @param $percentage * @param $message * @param bool $complete * @param bool $failed * @return bool */ public function setProgress($percentage, $message, $complete=false, $failed=false){ $process_data = array( 'percentage'=>$percentage, 'message' => $message, 'process_id' => self::$process_id, 'process_name' => self::$process_name, 'process_complete' => $complete, 'process_failed' => $failed, 'process_killed' => self::$process_killed, ); setcookie(self::$process_id."_percentage", $percentage, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_message", $message, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_name", self::$process_name, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_complete", $complete, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_failed", $failed, time() + (86400 * 30)); // 86400 = 1 day setcookie(self::$process_id."_process_killed", self::$process_killed, time() + (86400 * 30)); // 86400 = 1 day //verify if(isset($_COOKIE[self::$process_id])) return true; #delay 1 second //sleep(1); } }
Использование на стороне сервера при нажатии кнопки http://example.com/?progress
if(isset($_GET['progress'])){ ProcessProgress::settings(array( 'process_id' => 'upload_the_pix', 'process_name' => 'Picture Upload', )); ProcessProgress::setProgress(0, 'Initializing'); for($count=0; $count < 10001; $count++){ switch($count){ case 1000: ProcessProgress::setProgress(10, 'Coping files'); break; case 2000: ProcessProgress::setProgress(20, 'Setting up email'); break; case 3000: ProcessProgress::setProgress(30, 'Looking up things'); break; case 4000: ProcessProgress::setProgress(40, 'Milking your cow'); break; case 5000: ProcessProgress::setProgress(50, 'Syncing contacts'); break; case 6000: ProcessProgress::setProgress(60, 'Updating Facebook profile'); break; case 7000: ProcessProgress::setProgress(70, 'Calling your girl friend'); break; case 8000: ProcessProgress::setProgress(80, 'Making things up'); break; case 9000: ProcessProgress::setProgress(90, 'Feeding your dogs'); break; case 10000: ProcessProgress::setProgress(100, 'Done. Congrats'); break; } }
}
Независимо от технологии сервер / клиент, вы можете идти в двух направлениях:
После того, как вы переместите файл на сервере из temp, отправьте эхо пользователю, например «Файл успешно загружен. Обработка …» или только в JS, вы можете показать сообщение о событии завершения загрузки без какой-либо информации с сервера или сделать другой вызов ajax для проверки. .., действительно, есть много способов сделать что-то вроде этого. Дело в том, что после того, как сервер загрузок продолжает обработку файлов (например, OCR 30 страниц только что загруженного PDF или что-то еще), и пользователи должны ждать завершения обработки сервера. Это пахнет, потому что, если несколько пользователей загружают файлы одновременно, все будет обработано в одно и то же время, и ваш сервер будет быстро на 100% … поэтому это приводит меня к
После того, как документ будет загружен, поместите задание файла в очередь и сообщите пользователю, что вы отправите ему почту (или что бы вы ни делали для уведомления пользователей), когда обработка завершена (что-то вроде при отправке документа на получение). Таким образом обработка загруженных файлов (возможно, на другой машине;)) выполняется один за другим, и пользователям не придется ждать завершения обработки файлов … это предпочтительный способ.
Для очереди заданий / сообщений вы можете использовать:
Оба работают с Java, .NET, Ruby, Python, PHP, Perl, C / C ++, Erlang, Node.js, что не …
Удачи 🙂