Multiple XHR Request Progress Tracking - javascript

5 Requests is going on. If we take event.loaded it shows alternate values every time from random 5 progress events. How can we target each xhr requests?
var xhr = [];
for (i = 0; i < 5; i++) {
(function(i) {
var start = new Date().getTime();
xhr[i] = new XMLHttpRequest();
url = "/" + "?n=" + Math.random();
xhr[i].open("POST", url, true);
xhr[i].setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
xhr[i].upload.addEventListener("progress", progressHandler, false);
function progressHandler(event) {
end = new Date().getTime();
time = (end - start) / 1000;
var duration = time;
var bytes = event.loaded;
}
};
xhr[i].send(UploadData);

It's because you are using same handler for all 5 processes, you need individual handler for each. Then you can use shared scope to calculate overall progress:
var xhr = [];
var progress = [];
for (i = 0; i < 5; i++) {
(function(i) {
var start = new Date().getTime();
xhr[i] = new XMLHttpRequest();
url = "/" + "?n=" + Math.random();
xhr[i].open("POST", url, true);
xhr[i].setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
xhr[i].upload.addEventListener("progress", createProgressHandler(start, i), false);
xhr[i].send(UploadData);
// Initialize progress:
progress[i] = { bytes: 0 };
};
function createProgressHandler(start, i) {
return function (event) {
end = new Date().getTime();
time = (end - start) / 1000;
var duration = time;
var bytes = event.loaded;
progress[i].bytes = bytes;
console.log('Event from upload #' + i + ', bytes loaded: ' + bytes);
}
}

Related

Controlling file upload location in Google Drive (App script not form)

I'm implementing Kanshi Tanaike's Resumable Upload For Web Apps code and it works, but I don't fully understand the AJAX and am trying add a feature. Right now the code places the new file in the user's Drive root folder. I would either like to define a specific folder and upload there directly, or automatically move the file from root to the correct folder (I also need to collect the download link). I see the upload function references location in the response header, but I'm struggling to figure out how to define it, and since the doUpload() function does not seem to treat the upload as a File object I can't figure out how to reference it after the upload to acquire the URL or move it. Any feedback would be enormously appreciated.
$('#uploadfile').on("change", function() {
var file = this.files[0];
if (file.name != "") {
var fr = new FileReader();
fr.fileName = file.name;
fr.fileSize = file.size;
fr.fileType = file.type;
fr.onload = init;
fr.readAsArrayBuffer(file);
}
});
function init() {
$("#progress").text("Initializing.");
var fileName = this.fileName;
var fileSize = this.fileSize;
var fileType = this.fileType;
console.log({fileName: fileName, fileSize: fileSize, fileType: fileType});
var buf = this.result;
var chunkpot = getChunkpot(chunkSize, fileSize);
var uint8Array = new Uint8Array(buf);
var chunks = chunkpot.chunks.map(function(e) {
return {
data: uint8Array.slice(e.startByte, e.endByte + 1),
length: e.numByte,
range: "bytes " + e.startByte + "-" + e.endByte + "/" + chunkpot.total,
};
});
google.script.run.withSuccessHandler(function(at) {
var xhr = new XMLHttpRequest();
xhr.open("POST", "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable");
xhr.setRequestHeader('Authorization', "Bearer " + at);
xhr.setRequestHeader('Content-Type', "application/json");
xhr.send(JSON.stringify({
mimeType: fileType,
name: fileName,
}));
xhr.onload = function() {
doUpload({
location: xhr.getResponseHeader("location"),
chunks: chunks,
});
};
xhr.onerror = function() {
console.log(xhr.response);
};
}).getAt();
}
function doUpload(e) {
var chunks = e.chunks;
var location = e.location;
var cnt = 0;
var end = chunks.length;
var temp = function callback(cnt) {
var e = chunks[cnt];
var xhr = new XMLHttpRequest();
xhr.open("PUT", location, true);
xhr.setRequestHeader('Content-Range', e.range);
xhr.send(e.data);
xhr.onloadend = function() {
var status = xhr.status;
cnt += 1;
console.log("Uploading: " + status + " (" + cnt + " / " + end + ")");
$("#progress").text("Uploading: " + Math.floor(100 * cnt / end) + "%");
if (status == 308) {
callback(cnt);
} else if (status == 200) {
$("#progress").text("Done.");
} else {
$("#progress").text("Error: " + xhr.response);
}
};
}(cnt);
}
I believe your goal and your current situation as follows.
You want to upload a file to the specific folder.
You want to retrieve webContentLink of the uploaded file.
You want to achieve above using Resumable Upload for Web Apps using Google Apps Script
You have already confirmed that the default script at the repository worked.
Modification points:
In this case, it is required to check the resumable upload and the method of "Files: create" in Drive API.
In order to upload the file to the specific folder, please add the folder ID to the request body of the initial request.
In order to return the value of webContentLink, please use fields value to the initial request.
When above points are reflected to the original script, it becomes as follows.
Modified script:
In this case, HTML is modified.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.js"></script>
<title>Resumable upload for Web Apps</title>
</head>
<body>
<form>
<input name="file" id="uploadfile" type="file">
</form>
<div id="progress"></div>
<script>
const chunkSize = 5242880;
$('#uploadfile').on("change", function() {
var file = this.files[0];
if (file.name != "") {
var fr = new FileReader();
fr.fileName = file.name;
fr.fileSize = file.size;
fr.fileType = file.type;
fr.onload = init;
fr.readAsArrayBuffer(file);
}
});
function init() {
var folderId = "###"; // Added: Please set the folder ID.
$("#progress").text("Initializing.");
var fileName = this.fileName;
var fileSize = this.fileSize;
var fileType = this.fileType;
console.log({fileName: fileName, fileSize: fileSize, fileType: fileType});
var buf = this.result;
var chunkpot = getChunkpot(chunkSize, fileSize);
var uint8Array = new Uint8Array(buf);
var chunks = chunkpot.chunks.map(function(e) {
return {
data: uint8Array.slice(e.startByte, e.endByte + 1),
length: e.numByte,
range: "bytes " + e.startByte + "-" + e.endByte + "/" + chunkpot.total,
};
});
google.script.run.withSuccessHandler(function(at) {
var xhr = new XMLHttpRequest();
xhr.open("POST", "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&fields=*");
xhr.setRequestHeader('Authorization', "Bearer " + at);
xhr.setRequestHeader('Content-Type', "application/json");
xhr.send(JSON.stringify({
mimeType: fileType,
name: fileName,
parents: [folderId] // Added
}));
xhr.onload = function() {
doUpload({
location: xhr.getResponseHeader("location"),
chunks: chunks,
});
};
xhr.onerror = function() {
console.log(xhr.response);
};
}).getAt();
}
function doUpload(e) {
var chunks = e.chunks;
var location = e.location;
var cnt = 0;
var end = chunks.length;
var temp = function callback(cnt) {
var e = chunks[cnt];
var xhr = new XMLHttpRequest();
xhr.open("PUT", location, true);
xhr.setRequestHeader('Content-Range', e.range);
xhr.send(e.data);
xhr.onloadend = function() {
var status = xhr.status;
cnt += 1;
console.log("Uploading: " + status + " (" + cnt + " / " + end + ")");
$("#progress").text("Uploading: " + Math.floor(100 * cnt / end) + "%");
if (status == 308) {
callback(cnt);
} else if (status == 200) {
var metadata = JSON.parse(xhr.response); // Added
$("#progress").text("Done. Link: " + metadata.webContentLink); // Modified
} else {
$("#progress").text("Error: " + xhr.response);
}
};
}(cnt);
}
function getChunkpot(chunkSize, fileSize) {
var chunkPot = {};
chunkPot.total = fileSize;
chunkPot.chunks = [];
if (fileSize > chunkSize) {
var numE = chunkSize;
var endS = function(f, n) {
var c = f % n;
if (c == 0) {
return 0;
} else {
return c;
}
}(fileSize, numE);
var repeat = Math.floor(fileSize / numE);
for (var i = 0; i <= repeat; i++) {
var startAddress = i * numE;
var c = {};
c.startByte = startAddress;
if (i < repeat) {
c.endByte = startAddress + numE - 1;
c.numByte = numE;
chunkPot.chunks.push(c);
} else if (i == repeat && endS > 0) {
c.endByte = startAddress + endS - 1;
c.numByte = endS;
chunkPot.chunks.push(c);
}
}
} else {
var chunk = {
startByte: 0,
endByte: fileSize - 1,
numByte: fileSize,
};
chunkPot.chunks.push(chunk);
}
return chunkPot;
}
</script>
</body>
</html>
When the above modified script is run, the uploaded file is created to the specific folder and webContentLink is displayed as the result.
References:
Perform a resumable upload
Files: create
Resumable Upload for Web Apps using Google Apps Script

How to Execute Javascript inside html automatically and use ajax to send the variables into php?

I have found a java script that can measure user download speed and it is very close to the real speed and here is the code.
//JUST AN EXAMPLE, PLEASE USE YOUR OWN PICTURE!
var imageAddr = "http://www.kenrockwell.com/contax/images/g2/examples/31120037-5mb.jpg";
var downloadSize = 4995374; //bytes
function ShowProgressMessage(msg) {
if (console) {
if (typeof msg == "string") {
console.log(msg);
} else {
for (var i = 0; i < msg.length; i++) {
console.log(msg[i]);
}
}
}
var oProgress = document.getElementById("progress");
if (oProgress) {
var actualHTML = (typeof msg == "string") ? msg : msg.join("<br />");
oProgress.innerHTML = actualHTML;
}
}
function InitiateSpeedDetection() {
ShowProgressMessage("Loading the image, please wait...");
window.setTimeout(MeasureConnectionSpeed, 1);
};
if (window.addEventListener) {
window.addEventListener('load', InitiateSpeedDetection, false);
} else if (window.attachEvent) {
window.attachEvent('onload', InitiateSpeedDetection);
}
function MeasureConnectionSpeed() {
var startTime, endTime;
var download = new Image();
download.onload = function () {
endTime = (new Date()).getTime();
showResults();
}
download.onerror = function (err, msg) {
ShowProgressMessage("Invalid image, or error downloading");
}
startTime = (new Date()).getTime();
var cacheBuster = "?nnn=" + startTime;
download.src = imageAddr + cacheBuster;
function showResults() {
var duration = (endTime - startTime) / 1000;
var bitsLoaded = downloadSize * 8;
var speedBps = (bitsLoaded / duration).toFixed(2);
var speedKbps = (speedBps / 1024).toFixed(2);
var speedMbps = (speedKbps / 1024).toFixed(2);
ShowProgressMessage([
"Your connection speed is:",
speedBps + " bps",
speedKbps + " kbps",
speedMbps + " Mbps"
]);
}
}
I have really no experience with java script at all, First, I want to edit this code to execute without showing any messages at all and then I want it to run automatically in an empty html and using ajax to redirect page to a ( url + speedMbps javascript variable ).
For example, if the url is http://url.com/get.php?speed= and the speedMbps = 23 then I want the redirect url to look like that http://url.com/get.php?speed=23
Thank you very much for your help

show next/previous items of an array

I am using next/previous buttons to show the corresponding items of an array. I am experiencing two issues...
1) when the page loads, I need to click previous or next two times before anything will happen
2) Let's say I'm at record ID 10 for example. If I press 'next' 5 times to get to record ID 15, then press 'previous', instead of taking me to 14, it will take me to ID 16. If I then hit previous again (and subsequent times), the ID will then decrease as normal. Same thing with previous: If I start at ID 15 and hit previous down to 10, clicking 'next' will take me to ID 9 instead of 11. Then, subsequent clicks of 'next' will increase the ID as normal.
Hopefully this will help explain what I mean...
https://jsfiddle.net/mjcs351L/
This uses a super hero API. You will need your own to test the code but it's free and doesn't even ask you to sign up: https://www.superheroapi.com/
Thanks in advance for any guidance.
var apiKey = "YOUR API";
var charID = Math.floor((Math.random() * 731) + 1);
var website = "https://www.superheroapi.com/api.php/" + apiKey + "/" + charID;
var req = new XMLHttpRequest();
req.open('GET', website, true);
req.setRequestHeader('Content-Type', 'application/json');
req.addEventListener('load', function() {
var result = JSON.parse(req.responseText);
getinfo();
function getinfo() {
document.getElementById('fullname').innerHTML = result.biography["full-name"];
document.getElementById('name').innerHTML = result.name;
document.getElementById('egos').innerHTML = result.biography["alter-egos"];
document.getElementById('charID').innerHTML = result.id;
document.getElementById('birth').innerHTML = result.biography["place-of-birth"];
document.getElementById('height').innerHTML = result.appearance.height;
document.getElementById('weight').innerHTML = result.appearance.weight;
document.getElementById('gender').innerHTML = result.appearance.gender;
document.getElementById('race').innerHTML = result.appearance.race;
document.getElementById('eye').innerHTML = result.appearance["eye-color"];
document.getElementById('hair').innerHTML = result.appearance["hair-color"];
document.getElementById('occupation').innerHTML = result.work.occupation;
document.getElementById('connections').innerHTML = result.connections["group-affiliation"];
document.getElementById('relatives').innerHTML = result.connections.relatives;
document.getElementById("pic").src = result.image.url;
document.getElementById("pic").style.height = 300;
document.getElementById("pic").style.width = 300;
}
function nextItem() {
var test = charID + 1;
var website = "https://www.superheroapi.com/api.php/" + apiKey + "/" + test;
req.open('GET', website, true);
req.setRequestHeader('Content-Type', 'application/json');
req.addEventListener('load', function() {
var result = JSON.parse(req.responseText);
charID = test;
getinfo();
});
req.send(null);
}
function prevItem() {
var test = charID - 1;
var website = "https://www.superheroapi.com/api.php/" + apiKey + "/" + test;
req.open('GET', website, true);
req.setRequestHeader('Content-Type', 'application/json');
req.addEventListener('load', function() {
var result = JSON.parse(req.responseText);
charID = test;
getinfo();
});
req.send(null);
}
document.getElementById('prev_button').addEventListener('click', function(e) {
prevItem();
});
document.getElementById('next_button').addEventListener('click', function(e) {
nextItem();
});
event.preventDefault();
});
req.send(null);
You should try and follow DRY (don't repeat yourself), it makes it easier to debug code. I've tweaked the code a bit to re-use components.
var apiKey = "YOUR API";
var charID = Math.floor((Math.random() * 731) + 1);
function fetchData(id) {
id = id || charID;
var website = "https://www.superheroapi.com/api.php/" + apiKey + "/" + id;
var req = new XMLHttpRequest();
req.open('GET', website, true);
req.setRequestHeader('Content-Type', 'application/json');
req.addEventListener('load', function() {
var result = JSON.parse(req.responseText);
getinfo(result);
});
req.send(null);
}
fetchData()
function getinfo(result) {
document.getElementById('fullname').innerHTML = result.biography["full-name"];
document.getElementById('name').innerHTML = result.name;
document.getElementById('egos').innerHTML = result.biography["alter-egos"];
document.getElementById('charID').innerHTML = result.id;
document.getElementById('birth').innerHTML = result.biography["place-of-birth"];
document.getElementById('height').innerHTML = result.appearance.height;
document.getElementById('weight').innerHTML = result.appearance.weight;
document.getElementById('gender').innerHTML = result.appearance.gender;
document.getElementById('race').innerHTML = result.appearance.race;
document.getElementById('eye').innerHTML = result.appearance["eye-color"];
document.getElementById('hair').innerHTML = result.appearance["hair-color"];
document.getElementById('occupation').innerHTML = result.work.occupation;
document.getElementById('connections').innerHTML = result.connections["group-affiliation"];
document.getElementById('relatives').innerHTML = result.connections.relatives;
document.getElementById("pic").src = result.image.url;
document.getElementById("pic").style.height = 300;
document.getElementById("pic").style.width = 300;
}
function nextItem(ev) {
ev.preventDefault();
fetchData(++charID)
}
function prevItem(ev) {
ev.preventDefault();
fetchData(--charID)
}
document.getElementById('prev_button').addEventListener('click', prevItem);
document.getElementById('next_button').addEventListener('click', nextItem);

_formdataPolyfill2.default is not a constructor is thrown when I try to use formdata-polyfill npm

I am using web workers for uploading file and I am sending the file in the form of formData object as got to know that the web worker doesn't have access to DOM I used formdata-polyfill in place of default FormData , it is throwing this error and I don't know how to use this polyill properly.
here is my code,
//trying to send the formdata-polyfill object to worker
require('formdata-polyfill');
let data = new FormData();
data.append('server-method', 'upload');
data.append('file', event.target.files[0]);
// let data = new FormData(event.target.files[0]);
if (this.state.headerActiveTabUid === '1')
this.props.dispatch(handleFileUpload({upload: 'assets', data}));
//worker.js
var file = [], p = true, url,token;
function upload(blobOrFile) {
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);//add url to upload
xhr.setRequestHeader('Authorization', token);
xhr.onload = function(e) {
};
xhr.send(blobOrFile);
}
function process() {
for (var j = 0; j <file.length; j++) {
var blob = file[j];
const BYTES_PER_CHUNK = 1024 * 1024;
// 1MB chunk sizes.
const SIZE = blob.size;
var start = 0;
var end = BYTES_PER_CHUNK;
while (start < SIZE) {
if ('mozSlice' in blob) {
var chunk = blob.mozSlice(start, end);
} else {
var chunk = blob.slice(start, end);
}
upload(chunk);
start = end;
end = start + BYTES_PER_CHUNK;
}
p = ( j === file.length - 1);
self.postMessage(blob.name + " Uploaded Succesfully");
}
}
self.addEventListener('message', function(e) {
url = e.data.url;
token = e.data.id;
file.push(e.data.files);
if (p) {
process();
}
});

Blob data is not being sent to the PHP through XHR

I am trying to chunk a file and send to the server as follows
var fileselect = document.getElementById("file");
fileselect.addEventListener("change", FileSelectHandler, false);
function FileDragHover(e) {
e.stopPropagation();
e.preventDefault();
}
function FileSelectHandler(e) {
FileDragHover(e);
var blob = e.target.files[0] || e.dataTransfer.files[0];
worker = new Worker("fileupload.js");
worker.postMessage(blob);
worker.onmessage = function(e) {
console.log(e);
};
}
fileupload.js
self.onmessage = function(e) {
const BYTES_PER_CHUNK = 1024 * 1024 * 32;
var blob = new Blob([e.data]),
start = 0,
index = 0,
slices = Math.ceil(blob.size / BYTES_PER_CHUNK),
slices2 = slices;
while (start < blob.size) {
end = start + BYTES_PER_CHUNK;
if (end > blob.size) end = blob.size;
uploadChunk(blob, index, start, end, slices, slices2);
start = end;
index++;
}
};
function uploadChunk(blob, index, start, end, slices, slices2) {
var xhr = new XMLHttpRequest();
xhr.onload = function() {
slices--;
if (slices == 0) {
var xhrMerge = new XMLHttpRequest();
xhrMerge.open("POST", "uploadlargefile/?a=merge&name=" + blob.name + "&slices=" + slices2);
xhrMerge.onload = function() {
self.close();
};
xhrMerge.send();
}
};
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) self.postMessage(Math.round(100 / e.total * e.loaded)); //this doesn't work o.O
};
var chunk = blob.slice(start, end);
xhr.open("POST", "uploadlargefile/?a=chunk&name=" + blob.name + "&index=" + index);
xhr.setRequestHeader("Content-Type", "multipart\/form-data; boundary=--------------------");
xhr.send(chunk);
}
PHP
print_r($_GET['name']); print_r($_FILES);die;
I am able to get the name of the file but not the file . Any suggestion what could be wrong

Categories

Resources