html5 upload multiple files with javascript - javascript

here is the upload logic in js
var upload = function(){
if(_file.files.length === 0){
return;
}
var data = new FormData();
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){
_progress.style.width = Math.ceil(e.loaded/e.total) * 100 + '%';
}, false);
request.open('POST', 'upload.php');
request.send(data);
}
I run the function every time user selected something, but I only got the first file if user selected multiple files.

That's because you're only adding the first file to your data object:
data.append('SelectedFile', _file.files[0]);
You need to add all your files in the _file.files collection
Something like:
for(var i = 0 ; i < _file.files.length; i++ ) {
data.append('SelectedFile'+i, _file.files[i]);
}

var data = new FormData();
data.append('SelectedFile', _file.files[0]);
Instead of this code, try something like this:
var data = new FormData();
for (var i in _file.files) data.append('SelectedFile'+i, _file.files[i]);

Related

Sending location to the database directly

I have a script that allows to get the position (latitude & longitude) and after that it gets inserted in the input!
<script>
function maPosition(position) {
var x = position.coords.latitude;
var y= position.coords.longitude;
document.getElementById("x").value=x;
document.getElementById("y").value=y;
}
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(maPosition);
}
</script>
this is the result looks like!!
I want to, when the user allows the permission to get his position, the script automatically send the position (x,y) to the database without putting the position in the input (because I couldn't the position without putting them in the input)!!!
this is my script in NodeJs :
<script>
function ajouter() {
var url = "http://127.0.0.1:3000/reclamations";
var data = { };
data.location="X = "+document.getElementById("x").value;
data.location+="Y = "+document.getElementById("y").value;
var json = JSON.stringify(data);
console.log(json);
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader('Content-type','application/json; charset=utf-8');
xhr.onload = function () {
var users = JSON.parse(xhr.responseText);
if (xhr.readyState == 4 && xhr.status == "200") {
alert(" added !");
}
else {
console.table(users);
}
}
xhr.send(json);
}
</script>
Your code is very close, I added a button to make it easier to run here.
const ajouter = position => {
const url = "http://127.0.0.1:3000/reclamations";
// data is an object
let data = {};
// there are two properties - x and y which represent latitude and longitude
data.x = position.coords.latitude;
data.y = position.coords.longitude;
const json = JSON.stringify(data);
console.log(json);
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader('Content-type', 'application/json; charset=utf-8');
xhr.onload = function() {
const users = JSON.parse(xhr.responseText);
if (xhr.readyState == 4 && xhr.status == "200") {
alert(" added !");
} else {
console.table(users);
}
}
xhr.send(json);
}
// this will show an error to make it easier to debug
const error = e => console.log(e);
document.getElementById("go").addEventListener("click", evt => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(ajouter, error);
}
});
<button id="go">Go</button>
First off, I would create a reusable post function, so you can use Objects that automatically convert to FormData. Perhaps this will help:
function post(url, send, func, responseType ='json', context = null){
const x = new XMLHttpRequest;
if(typeof send === 'object' && send && !(send instanceof Array)){
const c = context || x;
x.open('POST', url); x.responseType = responseType;
x.onload = ()=>{
if(func)func.call(c, x.response);
}
x.onerror = e=>{
if(func)func.call(c, {xhrErrorEvent:e});
}
let d;
if(send instanceof FormData){
d = send;
}
else{
let s;
d = new FormData;
for(let k in send){
s = send[k];
if(typeof s === 'object' && s)s = JSON.stringify(s);
d.append(k, s);
}
}
x.send(d);
}
else{
throw new Error('send argument must be an Object');
}
return x;
}
function ajouter(){
navigator.geolocation.getCurrentPosition(position=>{
const pos = position.coords, data = {lat:pos.latitude, lng:pos.longitude, accuracy:pos.accuracy};
post('http://127.0.0.1:3000/reclamations', data, resp=>{
/* should echo json_encode($objOrAssocArray); in PHP - or send a JSON string back with node - resp will be JSON then - access like resp.property */
});
}, error=>{
throw new Error('error code:'+error.code+'; error message:'+error.message);
}, {enableHighAccuracy:true});
}

Sending ajax parameter to PHP script

I am working on a file drag and drop, and would like to use the same PHP page. I want to trigger the PHP script page using an action variable so it will go into the following if statement:
..
elseif ($_POST['action'] == 'uploadFile')
{
TrackEvent('CHANNEL_ACTIVATE');
echo "upload file";
}
I have an ajax call that is triggered using ondrop:
var data = new FormData();
data.append('action', 'uploadFile');
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.open('POST', 'channelEdit.php');
request.send(data);
$(this).unbind('click').click(function (e) {
});
$( "#fileList" ).trigger( "click" );
while you are sending post data in ajax you have to add setRequestHeader in request
So change your script as below :
var data = new FormData();
data.append('action', 'uploadFile');
var request = new XMLHttpRequest();
request.open('POST', 'channelEdit.php');
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); //<------Add this line
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.send(data);
$(this).unbind('click').click(function (e) {
});
$( "#fileList" ).trigger( "click" );

Get Byte Position during Upload Loop

I am working on a function that will write data to a remote server in chunks using a 3rd party API. Through some help on Stack Overflow I was able to accomplish this, where it is now working as expected. The problem is that I can only get a single 16kb chunk to write as I will need to advance the pos of where the next bytes are written to.
The initial write starts at 0 easily enough. Due to my unfamiliarity with this though, I am unsure if the next pos should just be 16 or what. If it helps, the API call writeFileChunk() takes 3 parameters, filepath (str), pos (int64), and data (base64 encoded string).
reader.onload = function(evt)
{
// Get SERVER_ID from URL
var server_id = getUrlParameter('id');
$("#upload_status").text('Uploading File...');
$("#upload_progress").progressbar('value', 0);
var chunkSize = 16<<10;
var buffer = evt.target.result;
var fileSize = buffer.byteLength;
var segments = Math.ceil(fileSize / chunkSize); // How many segments do we need to divide into for upload
var count = 0;
// start the file upload
(function upload()
{
var segSize = Math.min(chunkSize, fileSize - count * chunkSize);
if (segSize > 0)
{
$("#upload_progress").progressbar('value', (count / segments));
var chunk = new Uint8Array(buffer, count++ * chunkSize, segSize); // get a chunk
var chunkEncoded = btoa(String.fromCharCode.apply(null, chunk));
// Send Chunk data to server
$.ajax({
type: "POST",
url: "filemanagerHandler.php",
data: { 'action': 'writeFileChunk', 'server_id': server_id, 'filepath': filepath, 'pos': 0, 'chunk': chunkEncoded },
dataType: 'json',
success: function(data)
{
console.log(data);
setTimeout(upload, 100);
},
error: function(XMLHttpRequest, textStatus, errorThrown)
{
alert("Status: " + textStatus); alert("Error: " + errorThrown); alert("Message: " + XMLHttpRequest.responseText);
}
});
}
else
{
$("#upload_status").text('Finished!');
$("#upload_progress").progressbar('value', 100);
getDirectoryListing(curDirectory);
}
})()
};
The current position for the file on client side would be represented by this line, or more specifically the second argument at the pre-incremental step:
var chunk = new Uint8Array(buffer, count++ * chunkSize, segSize);
though, in this case it advances (count++) before you can reuse it so if you need the actual position (below as pos) you can extract it by simply rewriting the line into:
var pos = count++ * chunkSize; // here chunkSize = 16kb
var chunk = new Uint8Array(buffer, pos, segSize);
Here each position update will increment 16kb as that is the chunk-size. For progress then it is calculated pos / fileSize * 100. This of course assuming using the unencoded buffer size.
The only special case is the last chunk, but when there are no more chunks left to read the position should be equal to the file length (fileSize) so it should be pretty straight-forward.
When the ajax call return the server should have the same position unless something went wrong (connection, write access change, disk full etc.).
You can use Filereader API to read the chunks and send it to your remote server.
HTML
<input type="file" id="files" name="file" /> Read bytes:
<span class="readBytesButtons">
<button>Read entire file in chuncks</button>
</span>
Javascript
// Post data to your server.
function postChunk(obj) {
var url = "https://your.remote.server";
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open('post', url, true);
xhr.responseType = 'json';
xhr.onload = function() {
var status = xhr.status;
if (status == 200) {
resolve(xhr.response);
} else {
reject(status);
}
};
var params = "";
// check that obj has the proper keys and create the url parameters
if (obj.hasOwnProperty(action) && obj.hasOwnProperty(server_id) && obj.hasOwnProperty(filepath) && obj.hasOwnProperty(pos) && obj.hasOwnProperty(chunk)) {
params += "action="+obj[action]+"&server_id="+obj[server_id]+"&filepath="+obj[filepath]+"&pos="+obj[pos]+"&chunk="+obj[chunk];
}
if(params.length>0) {
xhr.send(params);
} else {
alert('Error');
}
});
}
// add chunk to "obj" object and post it to server
function addChunk(reader,obj,divID) {
reader.onloadend = function(evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
obj.chunk = evt.target.result;
console.log(obj);
document.getElementById(divID).textContent +=
['Sending bytes: ', obj.pos*16000, ' - ', ((obj.pos*16000)+(obj.pos+1)*obj.chunk.length),
'\n'].join('');
// post data to server
postChunk(obj).then(function(data) {
if(data!=="" && data!==null && typeof data!=="undefined") {
// chunk was sent successfully
document.getElementById(divID).textContent +=
['Sent bytes: ', obj.pos*16000, ' - ', ((obj.pos*16000)+(obj.pos+1)*obj.chunk.length),'\n'].join('');
} else {
alert('Error! Empty response');
}
}, function(status) {
alert('Resolve Error');
});
}
};
}
// read and send Chunk
function readChunk() {
var files = document.getElementById('files').files;
if (!files.length) {
alert('Please select a file!');
return;
}
var file = files[0];
var size = parseInt(file.size);
var chunkSize = 16000;
var chunks = Math.ceil(size/chunkSize);
var start,stop = 0;
var blob = [];
for(i=0;i<chunks;i++) {
start = i*chunkSize;
stop = (i+1)*chunkSize-1;
if(i==(chunks-1)) {
stop = size;
}
var reader = new FileReader();
blob = file.slice(start, stop);
reader.readAsBinaryString(blob);
var obj = {action: 'writeFileChunk', server_id: 'sid', filepath: 'path', pos: i, chunk: ""};
var div = document.createElement('div');
div.id = "bytes"+i;
document.body.appendChild(div);
addChunk(reader,obj,div.id);
}
}
// Check for the various File API support.
if (window.File && window.FileReader && window.FileList && window.Blob) {
console.log(' Great success! All the File APIs are supported.');
} else {
alert('The File APIs are not fully supported in this browser.');
}
document.querySelector('.readBytesButtons').addEventListener('click', function(evt) {
if (evt.target.tagName.toLowerCase() == 'button') {
readChunk();
}
}, false);
You can check this example in this Fiddle

FormData object, doesn't seem to be uploading my file...

Im following this guide to use aJax to upload an image, mainly so I can have a progress bar. But for some reason the PHP script doesn't seem to receive a file!
Here is my JavaScript:
function submitFile() {
var form = document.forms.namedItem("imageUpload");
var formData = new FormData(form);
var xhr = new XMLHttpRequest();
xhr.open("POST", "php/uploadImage.php", true);
xhr.onload = function(e) {
if (xhr.status == 200) {
console.log("uploaded!");
doc("imageResponse").innerHTML = xhr.responseText;
} else {
console.log("error!");
doc("imageResponse").innerHTML += "Error " + xhr.status + " occurred when trying to upload your file.<br \/>";
}
};
//Progress
/*
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
var currentPercentage = Math.round(e.loaded / e.total * 100);
document.getElementById("imageUpload").innerHTML = "UPLOAD IMAGE " + currentPercentage + "%";
document.getElementById("imageUpload").style.backgroundSize = currentPercentage + "% 100%";
}
};
*/
//Send data
xhr.send(formData);
}
And here is my PHP file which receives the file:
<?php
session_start();
print_r($_FILES);
?>
Currently that PHP file is returning an empty Array... it should have my file!
Array ( )
I managed to fix my code, here is the working version for anyone with the same problem. I decided to make a new form using JavaScript and append the file field value to this new form.
I did this mainly for my situation.
function submitFile(file,buttonId) {
//Generate a new form
var f = document.createElement("form");
f.setAttribute("method", "POST");
f.setAttribute("enctype", "multipart/form-data");
//Create FormData Object
var formData = new FormData(f);
//Append file
formData.append("image", file.files[0], "image.jpg");
var xhr = new XMLHttpRequest();
xhr.open("POST", "php/uploadImage.php", true);
xhr.onload = function(e) {
if (xhr.status == 200) {
document.getElementById(buttonId).innerHTML = "UPLOAD COMPLETE";
//console.log("uploaded!");
} else {
//console.log("error!");
alert("Error " + xhr.status + " occurred when trying to upload your file");
}
};
//Progress
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
var currentPercentage = Math.round(e.loaded / e.total * 100)-1;
document.getElementById(buttonId).innerHTML = "UPLOAD IMAGE " + currentPercentage + "%";
document.getElementById(buttonId).style.backgroundSize = (currentPercentage+1) + "% 100%";
if (currentPercentage==99) {
document.getElementById(buttonId).innerHTML = "Processing image";
}
}
};
//Send data
xhr.send(formData);
}

Calling data from JSON file using AJAX

I am trying to load some data from my JSON file using AJAX. The file is called external-file.json. Here is the code, it includes other parts that haven't got to do with the data loading.The part I'm not sure of begins in the getViaAjax funtion. I can't seem to find my error.
function flip(){
if(vlib_front.style.transform){
el.children[1].style.transform = "";
el.children[0].style.transform = "";
} else {
el.children[1].style.transform = "perspective(600px) rotateY(-180deg)";
el.children[0].style.transform = "perspective(600px) rotateY(0deg)";
}
}
var vlib_front = document.getElementById('front');
var el = document.getElementById('flip3D');
el.addEventListener('click', flip);
var word = null; var explanation = null;
var i=0;
function updateDiv(id, content) {
document.getElementById(id).innerHTML = content;
document.getElementById(id).innerHTML = content;
}
updateDiv('the-h',word[i]);
updateDiv('the-p',explanation[i])
function counter (index, step){
if (word[index+step] !== undefined) {
index+=step;
i=index;
updateDiv('the-h',word[index]);
updateDiv('the-p',explanation[index]);
}
}
var decos = document.getElementById('deco');
decos.addEventListener('click', function() {
counter(i,-1);
}, false);
var incos = document.getElementById('inco');
incos.addEventListener('click', function() {
counter(i,+1);
}, false);
function getViaAjax("external-file.json", callback) { // url being the url to external File holding the json
var r = new XMLHttpRequest();
r.open("GET", "external-file.json", true);
r.onload = function() {
if(this.status < 400 && this.status > 199) {
if(typeof callback === "function")
callback(JSON.parse(this.response));
} else {
console.log("err");// server reached but gave shitty status code}
};
}
r.onerror = function(err) {console.log("error Ajax.get "+url);console.log(err);}
r.send();
}
function yourLoadingFunction(jsonData) {
word = jsonData.words;
explanation = jsonData.explanation;
updateDiv('the-h',word[i]);
updateDiv('the-p',explanation[i])
// then call whatever it is to trigger the update within the page
}
getViaAjax("external-file.json", yourLoadingFunction)
As #light said, this:
function getViaAjax("external-file.json", callback) { // url being the url to external File holding the json
var r = new XMLHttpRequest();
r.open("GET", "external-file.json", true);
Should be:
function getViaAjax(url, callback) { // url being the url to external File holding the json
var r = new XMLHttpRequest();
r.open("GET", url, true);
I built up a quick sample that I can share that might help you isolate your issue. Stand this up in a local http-server of your choice and you should see JSON.parse(xhr.response) return a javascript array containing two objects.
There are two files
data.json
index.html
data.json
[{
"id":1,
"value":"foo"
},
{
"id":2,
"value":"bar"
}]
index.html
<html>
<head>
</head>
<body onload="so.getJsonStuffs()">
<h1>so.json-with-ajax</h1>
<script type="application/javascript">
var so = (function(){
function loadData(data){
var list = document.createElement("ul");
list.id = "data-list";
data.forEach(function(element){
var item = document.createElement("li");
var content = document.createTextNode(JSON.stringify(element));
item.appendChild(content);
list.appendChild(item);
});
document.body.appendChild(list);
}
var load = function()
{
console.log("Initializing xhr");
var xhr = new XMLHttpRequest();
xhr.onload = function(e){
console.log("response has returned");
if(xhr.status > 200
&& xhr.status < 400) {
var payload = JSON.parse(xhr.response);
console.log(payload);
loadData(payload);
}
}
var uri = "data.json";
console.log("opening resource request");
xhr.open("GET", uri, true);
xhr.send();
}
return {
getJsonStuffs : load
}
})();
</script>
</body>
</html>
Running will log two Javascript objects to the Dev Tools console as well as add a ul to the DOM containing a list item for every object inside the data.json array

Categories