Show Ajax Upload Status on Progress Element

File upload progress bar with jQuery

Note: This question is related to the jQuery form plugin. If you are searching for a pure jQuery solution, start here.
There is no overall jQuery solution for all browser. So you have to use a plugin. I am using dropzone.js, which have an easy fallback for older browsers. Which plugin you prefer depends on your needs. There are a lot of good comparing post out there.

From the examples:

jQuery:

$(function() {

var bar = $('.bar');
var percent = $('.percent');
var status = $('#status');

$('form').ajaxForm({
beforeSend: function() {
status.empty();
var percentVal = '0%';
bar.width(percentVal);
percent.html(percentVal);
},
uploadProgress: function(event, position, total, percentComplete) {
var percentVal = percentComplete + '%';
bar.width(percentVal);
percent.html(percentVal);
},
complete: function(xhr) {
status.html(xhr.responseText);
}
});
});

html:

<form action="file-echo2.php" method="post" enctype="multipart/form-data">
<input type="file" name="myfile"><br>
<input type="submit" value="Upload File to Server">
</form>

<div class="progress">
<div class="bar"></div >
<div class="percent">0%</div >
</div>

<div id="status"></div>

you have to style the progressbar with css...

How to get the file uploading progress status in ajax call?

You can use plUpload plugin to upload files..

Follow this link:https://www.plupload.com/docs
it has its own event for progressbar...

See the sample code below...

var uploader = new plupload.Uploader({
runtimes: 'html5,flash,silverlight,html4',
browse_button: 'pickfiles', // you can pass in id...
container: document.getElementById('container'), // ... or DOM Element itself
url: "//",
filters: {
max_file_size: '500mb',
mime_types: [
{ title: "PDF files", extensions: "pdf" }
]
},
flash_swf_url: '/plupload/js/Moxie.swf', // Flash settings
silverlight_xap_url: '/plupload/js/Moxie.xap', // Silverlight settings
init: {
PostInit: function () {
// whereas filelist is the divid which contains uploaded file names....
document.getElementById('filelist').innerHTML = '';

uploader.start();

},
FilesAdded: function (up, files) {
plupload.each(files, function (file) {
document.getElementById('filelist').innerHTML +=
'<div id ="' + file.id + '">' + file.name + ' (' + plupload.formatSize(file.size) +
') <b></b> <a href ="" class="remove text-danger pull-right">Remove</a></div>' +
'<div class="progressbar" id ="progressBar_' + file.id + '"> <div class="mybar" id="myBar' + file.id + '"></div></div>';
});

},
UploadProgress: function (up, file) {
var $progressId = $("#filelist div#progressBar_" + file.id + " div.mybar");
$progressId.css('width', file.percent + '%');
//To Remove 'Remove Link' while file is in uploading state.
$("#filelist div#" + file.id).find('a.remove').remove();
document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = '<span>' + file.percent + "%</span>";
},
FileUploaded: function (up, file, ServerResponse) {
var response = JSON.parse(ServerResponse.response);

},
UploadComplete: function (up, file) {
},
Error: function (up, err) {
document.getElementById('console').innerHTML += "\nError #" + err.code + ": " + err.message;
}
}
});
uploader.init();

I have used in my project have a look on snapshot below,

Sample Image

Show AJAX upload status on progress element

If your task is to upload a huge data-set or process it on the server, while updating progress to the server you should consider going with some sort of jobs architecture, where you initiate the job and do it with some other script running on the server (for example scaling / processing images etc). In this you do one thing at a time, thus forming a pipeline of tasks where there is an input and a final processed output.

At each step of pipeline the status of task is updated inside the database which can then be sent to the user by any server-push mechanism which exists these days. Running a single script which handles uploads and updates puts load on your server and also restricts you (what if the browser closes, what if some other error occurs). When process is divided into steps you can resume a failed task from the point where it succeeded last.

There exists many ways to do it. But the overall process flow looks like this

Sample Image

The following method is what I did for a personal project and this script held good for uploading and processing thousands of high resolution image to my server which then were scaled down into multiple versions and uploaded to amazon s3 while recognizing objects inside them. (My original code was in python)

Step 1 :

Initiate the transport or task

First Upload your content and then return a transaction id or uuid for this transaction immediately via a simple POST request. If you are doing multiple files or multiple things in the task, you may also want to handle that logic in this step

Step 2:

Do the job & Return the progress.

Once you have figured out how transactions occur you can then use any server side push technology to send update packet. I would choose WebSocket or Server Sent Events whichever applicable falling back to Long Polling on un-supported browsers. A simple SSE method would look like this.

function TrackProgress(upload_id){

var progress = document.getElementById(upload_id);
var source = new EventSource('/status/task/' + upload_id );

source.onmessage = function (event) {
var data = getData(event); // your custom method to get data, i am just using json here
progress.setAttribute('value', data.filesDone );
progress.setAttribute('max', data.filesTotal );
progress.setAttribute('min', 0);
};
}

request.post("/me/photos",{
files: files
}).then(function(data){
return data.upload_id;
}).then(TrackProgress);

On the server side, you will need to create something which keeps a track of the tasks, a simple Jobs architecture with job_id and progress sent to the db shall suffice. I would leave the job scheduling to you and the routing as well, but after that the conceptual code (for simplest SSE which will suffice the above code) is as follows.

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
/* Other code to take care of how do you find how many files are left
this is really not required */
function sendStatusViaSSE($task_id){
$status = getStatus($task_id);
$json_payload = array('filesDone' => $status.files_done,
'filesTotal' => $status.files_total);
echo 'data: ' . json_encode( $json_payload ) . '\n\n';
ob_flush();
flush();

// End of the game
if( $status.done ){
die();
}

}

while( True ){
sendStatusViaSSE( $request.$task_id );
sleep(4);
}

?>

A good tutorial on SSE can be found here http://html5doctor.com/server-sent-events/

and you can read more about pushing updates from the server on this question Pushing updates from server

The above was a conceptual explanation, there are other ways to achieve this but this was the solution that took care of a fairly huge task in my case.

Ajax file upload using core JavaScript with progress bar and additional fields

We can make a ajax request using core JavaScript with XHR for uploading the files.
Create below files:

/* ** upload.js ** */var submit = document.getElementById('submit'), file = document.getElementById('file'), title = document.getElementById('title');progress = document.getElementById('progress');
var upload = function(){
if(file.files.length === 0){ return; }
var data = new FormData(); data.append('title', title.value); data.append('SelectedFile', file.files[0]);
var request = new XMLHttpRequest(); request.onreadystatechange = function(){ if(request.readyState == 4){ try { var resp = JSON.parse(request.response); } catch (e){ var resp = { status: 'error', data: 'Unknown error occurred: [' + request.responseText + ']' }; } console.log(resp.status + ': ' + resp.data); } };
request.upload.addEventListener('progress', function(e){ var progress_width = Math.ceil(e.loaded/e.total * 100) + '%'; progress.style.width = progress_width; }, false);
request.open('POST', 'save.php'); request.send(data);}
submit.addEventListener('click', upload);
/* ** style.css ** */.container {    width: 500px;    margin: 0 auto;}.progress_outer {    border: 1px solid #000;}.progress {    width: 0%;    background: #DEDEDE;    height: 20px;  }
<!-- ** index.html ** --><!doctype html><html><head>    <meta charset="utf-8">    <title>JS File Upload with Progress</title>    <link rel="stylesheet" href="style.css"></head><body>    <div class='container'>        <p>            Enter Title: <input type='text' id='title'>        </p>        <br/>        <p>            Select File: <input type='file' id='file'>        </p>        <br/>        <input type='button' id='submit' value='Upload File'>        <div class='progress_outer'>            <div id='progress' class='progress'></div>        </div>    </div>    <script src='upload.js'></script></body></html>


Related Topics



Leave a reply



Submit