I am trying to upload some large files to the server using XMLHttpRequest and file.slice.
I've manage doing this with the help of documentations and other various links.
Since uploading large file is a lengthily job, i would like to provide the user with a progress bar.
After some more readings i've come across on an example that, theoretically, does exactly what i need.
By taking the sample code and adapting it to my needs i reached
var upload =
{
blobs: [],
pageName: '',
bytesPerChunk: 20 * 1024 * 1024,
currentChunk: 0,
loaded: 0,
total: 0,
file: null,
fileName: "",
uploadChunk: function (blob, fileName, fileType) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.responseText) {
// alert(xhr.responseText);
}
}
};
xhr.addEventListener("load", function (evt) {
$("#dvProgressPrcent").html("100%");
$get('dvProgress').style.width = '100%';
}, false);
xhr.addEventListener("progress", function (evt) {
if (evt.lengthComputable) {
var progress = Math.ceil(((upload.loaded + evt.loaded) / upload.total) * 100);
$("#dvProgressPrcent").html(progress + "%");
$get('dvProgress').style.width = progress + '%';
}
}, false);
xhr.upload.addEventListener("progress", function (evt) {
if (evt.lengthComputable) {
var progress = Math.ceil(((upload.loaded + evt.loaded) / upload.total) * 100);
$("#dvProgressPrcent").html(progress + "%");
$get('dvProgress').style.width = progress + '%';
}
}, false);
xhr.open('POST', upload.pageName, false);
xhr.setRequestHeader("Content-Type", "multipart/form-data");
xhr.setRequestHeader("X-File-Name", fileName);
xhr.setRequestHeader("X-File-Type", fileType);
xhr.send(blob);
},
upload: function (file) {
var start = 0;
var end = 0;
var size = file.size;
var date = new Date();
upload.fileName = date.format("dd.MM.yyyy_HH.mm.ss") + "_" + file.name;
upload.loaded = 0;
upload.total = file.size;
while (start < size) {
end = start + upload.bytesPerChunk;
if (end > size) {
end = size;
}
var blob = file.slice(start, end);
upload.uploadChunk(blob, upload.fileName, file.type);
start = end;
upload.loaded += start;
}
return upload.fileName;
}
};
The call is like (without the validations)
upload.upload(document.getElementById("#upload").files[0]);
My problem is that the progress event doesn't trigger.
I've tried xhr.addEventListener and with xhr.upload.addEventListener (each at a time and both at a time) for the progress event but it never triggers. The onreadystatechange and load events trigger just fine.
I would greatly appreciate help with what i am doing wrong
Update
After many attempts i've manage to simulate a progress but i've ran into another problem: Chrome's UI is not updating during the upload.
The code looks like this now
var upload =
{
pageName: '',
bytesPerChunk: 20 * 1024 * 1024,
loaded: 0,
total: 0,
file: null,
fileName: "",
uploadFile: function () {
var size = upload.file.size;
if (upload.loaded > size) return;
var end = upload.loaded + upload.bytesPerChunk;
if (end > size) { end = size; }
var blob = upload.file.slice(upload.loaded, end);
var xhr = new XMLHttpRequest();
xhr.open('POST', upload.pageName, false);
xhr.setRequestHeader("Content-Type", "multipart/form-data");
xhr.setRequestHeader("X-File-Name", upload.fileName);
xhr.setRequestHeader("X-File-Type", upload.file.type);
xhr.send(blob);
upload.loaded += upload.bytesPerChunk;
setTimeout(upload.updateProgress, 100);
setTimeout(upload.uploadFile, 100);
},
upload: function (file) {
upload.file = file;
var date = new Date();
upload.fileName = date.format("dd.MM.yyyy_HH.mm.ss") + "_" + file.name;
upload.loaded = 0;
upload.total = file.size;
setTimeout(upload.uploadFile, 100);
return upload.fileName;
},
updateProgress: function () {
var progress = Math.ceil(((upload.loaded) / upload.total) * 100);
if (progress > 100) progress = 100;
$("#dvProgressPrcent").html(progress + "%");
$get('dvProgress').style.width = progress + '%';
}
};
Update 2
I've managed to fix it and simulate a progress bar that works in chrome too.
i've updated previous code sample with the one that works.
You can make the bar 'refresh' more often by reducing the size of the chunk uploaded at a time
Tahnk you for your help
As stated in https://stackoverflow.com/a/3694435/460368, you could do :
if(xhr.upload)
xhr.upload.onprogress=upload.updateProgress;
and
updateProgress: function updateProgress(evt)
{
if (evt.lengthComputable) {
var progress = Math.ceil(((upload.loaded + evt.loaded) / upload.total) * 100);
$("#dvProgressPrcent").html(progress + "%");
$get('dvProgress').style.width = progress + '%';
}
}
There is my solution:
function addImages(id) {
var files = $("#files").prop("files");
var file = files[loopGallery];
var cList = files.length;
var fd = new FormData();
fd.append("file", file);
fd.append("galerie", id);
var xhr = new XMLHttpRequest();
xhr.open("POST", "moduls/galerie/uploadimages.php", true);
xhr.upload.onprogress = function(e) {
var percentComplete = Math.ceil((e.loaded / e.total) * 100);
$("#progress").css("display","");
$("#progressText").text((loopGallery+1)+" z "+cList);
$("#progressBar").css("width",percentComplete+"%");
};
xhr.onload = function() {
if(this.status == 200) {
$("#progressObsah").load("moduls/galerie/showimages.php?ids="+id);
if((loopGallery+1) == cList) {
loopGallery = 0;
} else {
$("#progressBar").css("width", "0%");
loopGallery++;
addImages(id);
}
}
}
if(cList > 0) {
xhr.send(fd);
}
}
Related
Trying to get multiple progress bars status with one XMLHttpRequest with a multifile upload. Cannot use jQuery and I do not have the option to loop through files and have the new XMLHttpRequests inside the loop due to client restrictions.
Currently I can have one progress bar for all files combined. What I need is multiple progress bar percentages. If I do a request.upload.onprogress inside the fileObj loop, then only the last progress bar will be updated.
let formData = new FormData();
let request = new XMLHttpRequest();
request.open('POST', postUrl);
for( var x in fileObj){
formData.append("file", fileObj[x]);
//this is where I tried to put the request.upload.onprogress with dynamic ids but failed.
}
request.upload.onprogress = function (e) {
if (e.lengthComputable) {
var percentComplete = (e.loaded / e.total) * 100;
d.getElementById("progress-bar" ).style.width = percentComplete + "%";
d.getElementById('progress-bar-output').innerHTML = Math.round(percentComplete) + "%";
}
};
request.onload = function (e) {
console.log( JSON.parse( e.target.response ) );
};
request.send(formData);
if fileObj is a FileList object, you could do the following
let formData = new FormData();
let request = new XMLHttpRequest();
let info = [];
let acc = 0;
request.open('POST', postUrl);
for (let x in fileObj){
const file = fileObj[x];
formData.append("file", file);
const cutoff = acc += file.size;
const index = info.length;
info.push({cutoff, size: file.size, name: file.name, index});
}
request.upload.addEventListener('progress', function (e) {
if (e.lengthComputable) {
const percentComplete = (e.loaded / e.total) * 100;
d.getElementById("progress-bar" ).style.width = percentComplete + "%";
d.getElementById('progress-bar-output').innerHTML = Math.round(percentComplete) + "%";
//
//
const file = info.find(({cutoff}) => cutoff <= e.loaded);
const thisPercentage = 100 * (e.loaded - (file.cutoff - file.size)) / file.size;
// display file progress here
// useful info: file.index - i.e. you could show `Uploading File ${file.name} ... ${file.index + 1} of ${info.length}`
}
});
request.addEventListener('load', function (e) {
console.log( JSON.parse( e.target.response ) );
};
request.send(formData);
I don't know how to do that, only two files sent to the server at the same time just like here UploadImages.In my code all the files are sent all at the same time. Here is my code. Words needed to fill the post. Words needed to fill the post.
var percent_info = document.querySelectorAll('.progress_bar:not(.trans_completed) .percent');
var p_bar = document.querySelectorAll('.progress_bar:not(.trans_completed)');
/* --- Upload files to server loop --- */
for (var i = 0; i < files.length; i++) {
uploadFile(files[i], percent_info[i], p_bar[i]);
}
function uploadFile(file, percent_info, p_bar) {
var url = "server/index.php";
if (file.type.match(imageType)) {
var xhr = new XMLHttpRequest();
var fd = new FormData();
xhr.upload.addEventListener("progress", function(evt) {
if (evt.lengthComputable) {
var percentLoaded = Math.round((evt.loaded / evt.total) * 100);
if (percentLoaded < 100) {
percent_info.style.width = percentLoaded + "%";
}
}
});
xhr.upload.addEventListener("load", function(e) {
var percentLoaded = Math.round((e.loaded / e.total) * 100);
percent_info.style.width = percentLoaded + "%";
});
function ready() {
return function() {
if (xhr.readyState == 4 && xhr.status == 200) {
p_bar.classList.add('trans_completed');
}
};
}
xhr.onreadystatechange = ready();
xhr.open("POST", url, true);
fd.append('uploaded_file', file);
xhr.send(fd);
}
};
I'm currently implementing an upload for files. Because I've to handle huge files here and there I've started to slice files and send them in 1mb chunks which works great as long as file are <~500MB after that it seems that memory isn't freed anyone randomly and I can't figure out what I'm missing here.
Prepare chunks
var sliceCount = 0;
var sendCount = 0;
var fileID = generateUUID();
var maxChunks = 0;
var userNotified = false;
function parseFile(file)
{
var fileSize = file.size;
var chunkSize = 1024 * 1024;//64 * 1024; // bytes
var offset = 0;
var self = this; // we need a reference to the current object
var chunkReaderBlock = null;
var numberOfChunks = fileSize / chunkSize;
maxChunks = Math.ceil(numberOfChunks);
// gets called if chunk is read into memory
var readEventHandler = function (evt)
{
if (evt.target.error == null) {
offset += evt.target.result.byteLength;
sendChunkAsBinary(evt.target.result);
}
else
{
console.log("Read error: " + evt.target.error);
return;
}
if (offset >= fileSize) {
console.log("Done reading file");
return;
}
// of to the next chunk
chunkReaderBlock(offset, chunkSize, file);
}
chunkReaderBlock = function (_offset, length, _file)
{
var r = new FileReader();
var blob = _file.slice(_offset, length + _offset);
sliceCount++;
console.log("Slicecount: " + sliceCount);
r.onload = readEventHandler;
r.readAsArrayBuffer(blob);
blob = null;
r = null;
}
// now let's start the read with the first block
chunkReaderBlock(offset, chunkSize, file);
}
Send Chunks
function sendChunkAsBinary(chunk)
{
var progressbar = $("#progressbar"), bar = progressbar.find('.uk-progress-bar');
// create XHR instance
var xhr = new XMLHttpRequest();
// send the file through POST
xhr.open("POST", 'upload.php', true);
var progressHandler = function (e)
{
// get percentage of how much of the current file has been sent
var position = e.loaded || e.position;
var total = e.total || e.totalSize;
var percentage = Math.round((sendCount / maxChunks) * 100);
// set bar width to keep track of progress
bar.css("width", percentage + "%").text(percentage + "%");
}
// let's track upload progress
var eventSource = xhr.upload || xhr;
eventSource.addEventListener("progress", progressHandler);
// state change observer - we need to know when and if the file was successfully uploaded
xhr.onreadystatechange = function ()
{
if (xhr.readyState == 4)
{
if (xhr.status == 200)
{
eventSource.removeEventListener("progress", progressHandler);
if (sendCount == maxChunks && !userNotified)
{
userNotified = true;
notifyUserSuccess("Datei hochgeladen!");
setTimeout(function ()
{
progressbar.addClass("uk-invisible");
bar.css("width", "0%").text("0%");
}, 250);
updateDocList();
}
}
else
{
notifyUser("Fehler beim hochladen der Datei!");
}
}
};
var blob;
if (typeof window.Blob == "function") {
blob = new Blob([chunk]);
} else {
var bb = new (window.MozBlobBuilder || window.WebKitBlobBuilder || window.BlobBuilder)();
bb.append(chunk);
blob = bb.getBlob();
}
sendCount++;
var formData = new FormData();
formData.append("chunkNumber", sendCount);
formData.append("maxChunks", maxChunks);
formData.append("fileID", fileID);
formData.append("chunkpart", blob);
xhr.send(formData);
progressbar.removeClass("uk-invisible");
console.log("Sendcount: " + sendCount);
}
If I attach to the debugger within Visual Studio 2015 it take a bit but soon I get an OutOfMemoryException in the send function at exactly this line: blob = new Blob([chunk]);. It's all the time the same line where the exception occures.
As soon as the Exception happens I get POST [...]/upload.php net::ERR_FILE_NOT_FOUND however I still got the chunks in my php-file.
Here's a Timeline-graph of my error
What I dont understand, I'm not able to see increasing memory inside the Task-Manager (a few mb of course but not close to 16gb ram I got).
So can anyone tell me where this leak comes from? What am I missing?
Is there a way in JS to get the progress of a loading image while the image is being loaded?
I want to use the new Progress tag of HTML5 to show the progress of loading images.
I wish there was something like:
var someImage = new Image()
someImage.onloadprogress = function(e) { progressBar.value = e.loaded / e.total };
someImage.src = "image.jpg";
With this, you add 2 new functions on the Image() object:
Image.prototype.load = function(url){
var thisImg = this;
var xmlHTTP = new XMLHttpRequest();
xmlHTTP.open('GET', url,true);
xmlHTTP.responseType = 'arraybuffer';
xmlHTTP.onload = function(e) {
var blob = new Blob([this.response]);
thisImg.src = window.URL.createObjectURL(blob);
};
xmlHTTP.onprogress = function(e) {
thisImg.completedPercentage = parseInt((e.loaded / e.total) * 100);
};
xmlHTTP.onloadstart = function() {
thisImg.completedPercentage = 0;
};
xmlHTTP.send();
};
Image.prototype.completedPercentage = 0;
And here you use the load function and append the image on a div.
var img = new Image();
img.load("url");
document.getElementById("myDiv").appendChild(img);
During the loading state you can check the progress percentage using img.completedPercentage.
Sebastian's answer is excellent, the best I've seen to this question. There are, however, a few possible improvements. I use his code modified like this:
Image.prototype.load = function( url, callback ) {
var thisImg = this,
xmlHTTP = new XMLHttpRequest();
thisImg.completedPercentage = 0;
xmlHTTP.open( 'GET', url , true );
xmlHTTP.responseType = 'arraybuffer';
xmlHTTP.onload = function( e ) {
var h = xmlHTTP.getAllResponseHeaders(),
m = h.match( /^Content-Type\:\s*(.*?)$/mi ),
mimeType = m[ 1 ] || 'image/png';
// Remove your progress bar or whatever here. Load is done.
var blob = new Blob( [ this.response ], { type: mimeType } );
thisImg.src = window.URL.createObjectURL( blob );
if ( callback ) callback( this );
};
xmlHTTP.onprogress = function( e ) {
if ( e.lengthComputable )
thisImg.completedPercentage = parseInt( ( e.loaded / e.total ) * 100 );
// Update your progress bar here. Make sure to check if the progress value
// has changed to avoid spamming the DOM.
// Something like:
// if ( prevValue != thisImage completedPercentage ) display_progress();
};
xmlHTTP.onloadstart = function() {
// Display your progress bar here, starting at 0
thisImg.completedPercentage = 0;
};
xmlHTTP.onloadend = function() {
// You can also remove your progress bar here, if you like.
thisImg.completedPercentage = 100;
}
xmlHTTP.send();
};
Mainly I added a mime-type and some minor details. Use as Sebastian describes. Works well.
Just to add to the improvements, I've modified Julian's answer (which in turn modified Sebastian's). I've moved the logic to a function instead of modifying the Image object. This function returns a Promise that resolves with the URL object, which only needs to be inserted as the src attribute of an image tag.
/**
* Loads an image with progress callback.
*
* The `onprogress` callback will be called by XMLHttpRequest's onprogress
* event, and will receive the loading progress ratio as an whole number.
* However, if it's not possible to compute the progress ratio, `onprogress`
* will be called only once passing -1 as progress value. This is useful to,
* for example, change the progress animation to an undefined animation.
*
* #param {string} imageUrl The image to load
* #param {Function} onprogress
* #return {Promise}
*/
function loadImage(imageUrl, onprogress) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
var notifiedNotComputable = false;
xhr.open('GET', imageUrl, true);
xhr.responseType = 'arraybuffer';
xhr.onprogress = function(ev) {
if (ev.lengthComputable) {
onprogress(parseInt((ev.loaded / ev.total) * 100));
} else {
if (!notifiedNotComputable) {
notifiedNotComputable = true;
onprogress(-1);
}
}
}
xhr.onloadend = function() {
if (!xhr.status.toString().match(/^2/)) {
reject(xhr);
} else {
if (!notifiedNotComputable) {
onprogress(100);
}
var options = {}
var headers = xhr.getAllResponseHeaders();
var m = headers.match(/^Content-Type\:\s*(.*?)$/mi);
if (m && m[1]) {
options.type = m[1];
}
var blob = new Blob([this.response], options);
resolve(window.URL.createObjectURL(blob));
}
}
xhr.send();
});
}
/*****************
* Example usage
*/
var imgContainer = document.getElementById('imgcont');
var progressBar = document.getElementById('progress');
var imageUrl = 'https://placekitten.com/g/2000/2000';
loadImage(imageUrl, (ratio) => {
if (ratio == -1) {
// Ratio not computable. Let's make this bar an undefined one.
// Remember that since ratio isn't computable, calling this function
// makes no further sense, so it won't be called again.
progressBar.removeAttribute('value');
} else {
// We have progress ratio; update the bar.
progressBar.value = ratio;
}
})
.then(imgSrc => {
// Loading successfuly complete; set the image and probably do other stuff.
imgContainer.src = imgSrc;
}, xhr => {
// An error occured. We have the XHR object to see what happened.
});
<progress id="progress" value="0" max="100" style="width: 100%;"></progress>
<img id="imgcont" />
Actually, in latest chrome you can use it.
$progress = document.querySelector('#progress');
var url = 'https://placekitten.com/g/2000/2000';
var request = new XMLHttpRequest();
request.onprogress = onProgress;
request.onload = onComplete;
request.onerror = onError;
function onProgress(event) {
if (!event.lengthComputable) {
return;
}
var loaded = event.loaded;
var total = event.total;
var progress = (loaded / total).toFixed(2);
$progress.textContent = 'Loading... ' + parseInt(progress * 100) + ' %';
console.log(progress);
}
function onComplete(event) {
var $img = document.createElement('img');
$img.setAttribute('src', url);
$progress.appendChild($img);
console.log('complete', url);
}
function onError(event) {
console.log('error');
}
$progress.addEventListener('click', function() {
request.open('GET', url, true);
request.overrideMimeType('text/plain; charset=x-user-defined');
request.send(null);
});
<div id="progress">Click me to load</div>
Here is a small update of the code of Julian Jensen in order to be able to draw the image in a Canvas after it is loaded :
xmlHTTP.onload = function( e ) {
var h = xmlHTTP.getAllResponseHeaders(),
m = h.match( /^Content-Type\:\s*(.*?)$/mi ),
mimeType = m[ 1 ] || 'image/png';
// Remove your progress bar or whatever here. Load is done.
var blob = new Blob( [ this.response ], { type: mimeType } );
thisImg.src = window.URL.createObjectURL( blob );
thisImg.onload = function()
{
if ( callback ) callback( this );
};
};
for xmlhttpreq v2 check, use:
var xmlHTTP = new XMLHttpRequest();
if ('onprogress' in xmlHTTP) {
// supported
} else {
// isn't supported
}
If you want to process your loaded image, than you have to add one more function, because
thisImg.src = window.URL.createObjectURL(blob)
just starts to process the image as a thread.
You have to add a new a function to the body of load prototype, like
this.onload = function(e)
{
var canvas = document.createElement('canvas')
canvas.width = this.width
canvas.height = this.height
canvas.getContext('2d').drawImage(this, 0, 0)
}
This make me headache to realize :)
I use this code to upload files, and this code have a progressbar. The problem with this code is that it never send me to "upload.php" after it have uploaded the file, after it reach 100% on the progressbar. (It's not my code).
The code:
// get form data for POSTing
//var vFD = document.getElementById('upload_form').getFormData(); // for FF3
var vFD = new FormData(document.getElementById('upload_form'));
// create XMLHttpRequest object, adding few event listeners, and POSTing our data
var oXHR = new XMLHttpRequest();
oXHR.upload.addEventListener('progress', uploadProgress, false);
oXHR.addEventListener('load', uploadFinish, false);
oXHR.addEventListener('error', uploadError, false);
oXHR.addEventListener('abort', uploadAbort, false);
oXHR.open('POST', 'upload.php');
oXHR.send(vFD);
The whole script
// common variables
var iBytesUploaded = 0;
var iBytesTotal = 0;
var iPreviousBytesLoaded = 0;
var iMaxFilesize = 1048576; // 1MB
var oTimer = 0;
var sResultFileSize = '';
var uploadingcanceld = "حدث خطأ أثناء تحميل الملف";
function secondsToTime(secs) { // we will use this function to convert seconds in normal time format
var hr = Math.floor(secs / 3600);
var min = Math.floor((secs - (hr * 3600))/60);
var sec = Math.floor(secs - (hr * 3600) - (min * 60));
if (hr < 10) {hr = "0" + hr; }
if (min < 10) {min = "0" + min;}
if (sec < 10) {sec = "0" + sec;}
if (hr) {hr = "00";}
return hr + ':' + min + ':' + sec;
};
function bytesToSize(bytes) {
var sizes = ['Bytes', 'KB', 'MB'];
if (bytes == 0) return 'n/a';
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
return (bytes / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i];
};
function fileSelected() {
// hide different warnings
document.getElementById('upload_response').style.display = 'none';
document.getElementById('error').style.display = 'none';
document.getElementById('error2').style.display = 'none';
document.getElementById('abort').style.display = 'none';
document.getElementById('warnsize').style.display = 'none';
// get selected file element
var oFile = document.getElementById('ufile').files[0];
// filter for image files
var rFilter = /^(image\/bmp|image\/gif|image\/jpeg|image\/png|image\/tiff)$/i;
if (! rFilter.test(oFile.type)) {
document.getElementById('error').style.display = 'block';
return;
}
// little test for filesize
if (oFile.size > iMaxFilesize) {
document.getElementById('warnsize').style.display = 'block';
return;
}
// get preview element
var oImage = document.getElementById('preview');
// prepare HTML5 FileReader
var oReader = new FileReader();
oReader.onload = function(e){
// e.target.result contains the DataURL which we will use as a source of the image
oImage.src = e.target.result;
oImage.onload = function () { // binding onload event
// we are going to display some custom image information here
sResultFileSize = bytesToSize(oFile.size);
document.getElementById('fileinfo').style.display = 'block';
document.getElementById('filename').innerHTML = 'Name: ' + oFile.name;
document.getElementById('filesize').innerHTML = 'Size: ' + sResultFileSize;
document.getElementById('filetype').innerHTML = 'Type: ' + oFile.type;
document.getElementById('filedim').innerHTML = 'Dimension: ' + oImage.naturalWidth + ' x ' + oImage.naturalHeight;
};
};
// read selected file as DataURL
oReader.readAsDataURL(oFile);
}
function startUploading() {
// cleanup all temp states
iPreviousBytesLoaded = 0;
$("#upload").animate({height:'75px'},350);
$("#loadingborders").fadeIn(1500);
$("#progress_percent").fadeIn(1500);
$("#upload_button").fadeOut(100);
$("#ufile").fadeOut(100);
document.getElementById('ufile').style.margin = '5px 0px -5px 0px';
document.getElementById('upload_response').style.display = 'none';
document.getElementById('error').style.display = 'none';
document.getElementById('error2').style.display = 'none';
document.getElementById('abort').style.display = 'none';
document.getElementById('warnsize').style.display = 'none';
document.getElementById('progress_percent').innerHTML = '';
var oProgress = document.getElementById('progress');
oProgress.style.display = 'block';
oProgress.style.width = '0px';
// get form data for POSTing
//var vFD = document.getElementById('upload_form').getFormData(); // for FF3
var vFD = new FormData(document.getElementById('upload_form'));
// create XMLHttpRequest object, adding few event listeners, and POSTing our data
var oXHR = new XMLHttpRequest();
oXHR.upload.addEventListener('progress', uploadProgress, false);
oXHR.addEventListener('load', uploadFinish, false);
oXHR.addEventListener('error', uploadError, false);
oXHR.addEventListener('abort', uploadAbort, false);
oXHR.open('POST', 'upload.php');
oXHR.send(vFD);
// set inner timer
oTimer = setInterval(doInnerUpdates, 300);
}
function doInnerUpdates() { // we will use this function to display upload speed
var iCB = iBytesUploaded;
var iDiff = iCB - iPreviousBytesLoaded;
// if nothing new loaded - exit
if (iDiff == 0)
return;
iPreviousBytesLoaded = iCB;
iDiff = iDiff * 2;
var iBytesRem = iBytesTotal - iPreviousBytesLoaded;
var secondsRemaining = iBytesRem / iDiff;
// update speed info
var iSpeed = iDiff.toString() + 'B/s';
if (iDiff > 1024 * 1024) {
iSpeed = (Math.round(iDiff * 100/(1024*1024))/100).toString() + 'MB/s';
} else if (iDiff > 1024) {
iSpeed = (Math.round(iDiff * 100/1024)/100).toString() + 'KB/s';
}
document.getElementById('speed').innerHTML = iSpeed;
document.getElementById('remaining').innerHTML = '| ' + secondsToTime(secondsRemaining);
}
function uploadProgress(e) { // upload process in progress
if (e.lengthComputable) {
iBytesUploaded = e.loaded;
iBytesTotal = e.total;
var iPercentComplete = Math.round(e.loaded * 100 / e.total);
var iBytesTransfered = bytesToSize(iBytesUploaded);
document.getElementById('progress_percent').innerHTML = iPercentComplete.toString() + '%';
document.getElementById('progress').style.width = (iPercentComplete * 4).toString() + 'px';
document.getElementById('b_transfered').innerHTML = iBytesTransfered;
if (iPercentComplete == 100) {
var oUploadResponse = document.getElementById('upload_response');
oUploadResponse.innerHTML = '<h1>Please wait...processing</h1>';
}
} else {
document.getElementById('progress').innerHTML = 'unable to compute';
}
}
function uploadFinish(e) { // upload successfully finished
var oUploadResponse = document.getElementById('upload_response');
oUploadResponse.innerHTML = e.target.responseText;
document.getElementById('progress_percent').innerHTML = '100%';
document.getElementById('progress').style.width = '400px';
document.getElementById('filesize').innerHTML = sResultFileSize;
document.getElementById('remaining').innerHTML = '| 00:00:00';
clearInterval(oTimer);
}
function uploadError(e) { // upload error
$('#errormessage').slideUp('fast', function() {
$('#errormessage').html(uploadingcanceld);
$('#errormessage').slideDown('fast');
});
clearInterval(oTimer);
}
function uploadAbort(e) { // upload abort
clearInterval(oTimer);
}
XHR is a dynamic data call, it's not a document forwarding call, meaning the reason why we have XHR to begin with is so that we DON'T want to forward a client to another page to get new content into the page. So you might want to wait on the XHR to complete the process of sending the data, acquire the results of that transfer via XHR, and based on those results do as you want.
So in essence, you are creating a virtual document client/server transfer and handshake without having to forward the client, that of which is the role XHR was created to fulfill.