Download the course with subsequent processing

I have a upload form where users can upload files. After the download is complete, the files are processed after processing, and sometimes processing takes 10-15 seconds after the download is completed.

After the download is completed, the progress bar is at 100%, but how can you determine when the file has finished so that you can show the user a β€œwait” sign while the file is being processed. The user might think that the browser froze and crashed, because the progress bar is at 100%, but nothing happens.

Pure HTML5 + javascript client solution is preferred but not required :)

+5
source share
6 answers

Try

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; }) }); / gif; charset = binary; base64, R0lGODlhEAAQAPIAAP /// wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH + GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAKAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa + dIAAAh + QQACgABACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkEAAoAAgAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkEAAoAAwAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo / IpHI5TAAAIfkEAAoABAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo / IpFKSAAAh + QQACgAFACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh + QQACgAGACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAAKAAcALAAAAAAQABAAAAMyCLrc / jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA ==" 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; }) }); 

jsfiddle http://jsfiddle.net/guest271314/d2szrs20/

+8
source

Since you have a progress bar to display the process of the form. To add more details, and from processing, you can add an image similar to below

It will show the user that your form is still in the process. Create your own image here

enter image description here

This can help the user - the browser is not frozen.

+5
source

I am using a custom download widget for this. On the server side, I send the following information to the client when it asks for an update: Percentage of received file plus status message. Through the message, I can give additional feedback, for example, what stage of the message processing occurs or display errors.

+2
source

I use a jquery plugin called pekeupload. It is small and easy to implement and configure.

http://plugins.jquery.com/pekeUpload/ https://github.com/pekebyte/pekeUpload

I hope this helps you

it's better

+2
source

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> 

Server process - using 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); } } 

Server-side use when clicking the http://example.com/?progress button

  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; } } 

}

+2
source

Regardless of server / client technology, you can go in two directions:

1. First with linear processing (this is you at present)

After you move the file to the server from temp, send an echo to the user, for example, "The file has been successfully uploaded. Processing ..." or just in JS you can show a message about the download completion event without any information from the server or make another call ajax to check ... there really are many ways for something like this. The fact is that after the download server continues to process files (for example, OCR 30 pages of a freshly downloaded PDF file or something else), and users must wait for server processing to complete, this smells because if several users download files at the same time, everything will be processed at the same time, and your server will be 100% fast ... so this leads me to

2. Using job / message queues

After the document has been downloaded, put the file task in the queue and tell the user that you will send him mail (or whatever you do to notify users) when processing is completed (something like sending a document to receive). Thus, the processing of downloaded files (possibly on another machine;)) is performed one after another, and users do not have to wait for the completion of file processing ... this is the preferred method.

For a job / message queue, you can use:

Both work with Java, .NET, Ruby, Python, PHP, Perl, C / C ++, Erlang, Node.js, which does not ...

Good luck :)

0
source

Source: https://habr.com/ru/post/1210051/