Reputation: 403
Hello everyone I'm here again. I'm trying to write a code that's able to resize all images before they're uploaded to the server. Once these images are in server-side, I need to know which array they belong to treat each one differently. For this purpose I'm using two arrays taht's get files from two inputs as shown in the code below:
HTML
<form method="post">
<input type="file" name="one[]" id="one" accept="image/jpeg, image/jpg" size="6" multiple/>
<input type="file" name="two[]" id="two" accept="image/jpeg, image/jpg" size="6" multiple/>
<button type="submit" id="submitButton">Submit</button>
</form>
JAVASCRIPT
var imgMaxWidth = 1014; //Max width to resized image
var imgMaxHeight = 1350; //Max height to resized images
var arrayOne = [];
var arrayTwo = [];
var arrayTest = ['zero', 'one', 'two'];
$(function() {
var submitButton = $("#submitButton")
/**
* Resizes all images before upload
* @param {object?} input that contain images files
* @param {array} arrayIndex decides which array to push
*/
var resizeBeforeUpload = function(input, arrayIndex) {
// Checks has inputed files
if (input.files) {
// count files
var filesAmount = input.files.length;
// loop through files
for (i = 0; i < filesAmount; i++) {
// creates file reader object
var reader = new FileReader();
// awaits load end
reader.onloadend = function(event) {
var tempImg = new Image();
tempImg.src = event.target.result;
// execute when images load
tempImg.onload = function() {
// Assigns the variables according to previously defined limits
var MAX_WIDTH = imgMaxWidth; //imgMaxWidth = 1014;
var MAX_HEIGHT = imgMaxHeight; //imgMaxHeight = 1350;
var tempW = tempImg.width;
var tempH = tempImg.height;
// Handles de sizes correction
if (tempW > tempH) // is width greater than height?
{
if (tempW > MAX_WIDTH) { // is image.width greater than MAX_WIDTH variable?
// Image.height equals Image.height * MAX_WIDTH divided by image.width
tempH *= MAX_WIDTH / tempW;
tempW = MAX_WIDTH;
}
} else {
if (tempH > MAX_HEIGHT) {
tempW *= MAX_HEIGHT / tempH;
tempH = MAX_HEIGHT;
}
}
// Creates a canvas element
var canvas = document.createElement('canvas');
// Assigns width and height to canvas
canvas.width = tempW;
canvas.height = tempH;
// Returns a bidimensional drawing context on canvas
var ctx = canvas.getContext("2d");
// Draw the image
ctx.drawImage(this, 0, 0, tempW, tempH);
/* Returns a base64 from the canvas,
[0.6] is a image quality indicator -> [from 0.1=low, to 1.0=high]*/
var dataURL = canvas.toDataURL("image/jpeg", 0.6);
// *** here starts the mess ***
// I added the index checking to be able to separate arrays
if (arrayIndex == 1) {
// push this array
arrayOne.push(dataURL);
} else if (arrayIndex == 2) {
// push this array
arrayTwo.push(dataURL);
}
}
}
reader.readAsDataURL(input.files[i]);
}
}
};
// On click form submit button
submitButton.unbind().click(function(e){
$(this).prop("disabled", true);
// prevent default submiting form
e.preventDefault();
// run resizeBeforeUpload(input, index=1);
resizeBeforeUpload(document.getElementById('one'), 1)
console.log(arrayOne);
// run resizeBeforeUpload(input, index=2);
resizeBeforeUpload(document.getElementById('two'), 2)
console.log(arrayTwo);
console.log(arrayTest);
});
});
But when I send the form by clicking its button, the data is sent incompletely. Sometimes I get all arrays with all images, but sometimes only some images are being uploaded. I believe this is happening because the form is being submitted before the entire array is filled. Could you help me resolve this issue? I need to get the list of images from each of the inputs, then I need each of these images reduced, then I need them to be uploaded to the server in base64 format. Something like this:
data = 'firstArray='+arrayOne+'&secondArray='+arrayTwo;
xhr.send(data);
With each of the arrays separate I'll be able to put each of them in different tables in the database:
[...]
$firstArray = $_POST[firstArray][i];
$secondArray = $_POST[secondArray][i];
[...]
Here's a fiddle example: link
Upvotes: 0
Views: 82
Reputation: 1099
Javascript doesn't wait for asynchronous functions. When resizeBeforeUpload
is finished, reader.onloadend
will not be executed yet. You should make resizeBeforeUpload
function to return a promise.
In the submit function you should wait both to finish with Promise.all
.
Your functions should look like below.
var imgMaxWidth = 1014; //Max width to resized image
var imgMaxHeight = 1350; //Max height to resized images
var arrayOne = [];
var arrayTwo = [];
var arrayTest = ['zero', 'one', 'two'];
$(function() {
var submitButton = $("#submitButton")
/**
* Resizes all images before upload
* @param {object?} input thats contain images files
* @param {array} arrayIndex decides which array to push
*/
var resizeBeforeUpload = function(file) {
return new Promise(resolve => {
// creates file reader object
var reader = new FileReader();
// awaits load end
reader.onloadend = function(event) {
var tempImg = new Image();
tempImg.src = event.target.result;
// execute when images load
tempImg.onload = function() {
// Assigns the variables according to previously defined limits
var MAX_WIDTH = imgMaxWidth; //imgMaxWidth = 1014;
var MAX_HEIGHT = imgMaxHeight; //imgMaxHeight = 1350;
var tempW = tempImg.width;
var tempH = tempImg.height;
// Handles de sizes correction
if (tempW > tempH) // is width greater than height?
{
if (tempW > MAX_WIDTH) { // is image.width greater than MAX_WIDTH variable?
// Image.height equals Image.height * MAX_WIDTH divided by image.width
tempH *= MAX_WIDTH / tempW;
tempW = MAX_WIDTH;
}
} else {
if (tempH > MAX_HEIGHT) {
tempW *= MAX_HEIGHT / tempH;
tempH = MAX_HEIGHT;
}
}
// Creates a canvas element
var canvas = document.createElement('canvas');
// Assigns width and height to canvas
canvas.width = tempW;
canvas.height = tempH;
// Returns a bidimensional drawing context on canvas
var ctx = canvas.getContext("2d");
// Draw the image
ctx.drawImage(this, 0, 0, tempW, tempH);
/* Returns a base64 from the canvas,
[0.6] is a image quality indicator -> [from 0.1=low, to 1.0=high]*/
var dataURL = canvas.toDataURL("image/jpeg", 0.6);
resolve(dataURL);
}
}
reader.readAsDataURL(file);
});
};
var getFiles = (inputElement) => {
const promiseArray = Array.from(inputElement.files).map(file => resizeBeforeUpload(file));
return Promise.all(promiseArray);
};
// On click form submit button
submitButton.unbind().click(function(e){
$(this).prop("disabled", true);
// prevent default submiting form
e.preventDefault();
Promise.all([
getFiles(document.getElementById('one')),
getFiles(document.getElementById('two')),
]).then(([oneResults, twoResults]) => {
console.log(oneResults);
console.log(twoResults);
})
});
});
Upvotes: 1