React - Image Uploader only allow transparent images - javascript

I want to check the image alpha channel to see if it has a background, and reject it if true, allow it if false but when I upload an image using the const changefile, the hasAlpha function doesn't serve an 'error' alert if the image has a background.
Function for checking if the image has a transparent background:
export function hasAlpha(file) {
return new Promise((resolve, reject) => {
let hasAlpha = false;
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
const img = new Image();
img.crossOrigin = "Anonymous";
img.onerror = reject;
img.onload = function () {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
for (let j = 0; j < imgData.length; j += 4) {
if (imgData[j + 3] < 255) {
hasAlpha = true;
break;
}
}
resolve(hasAlpha);
};
img.src = URL.createObjectURL(file);
});
}
Where the image is uploaded:
const changefile = async (e) => {
if (e.target.id === "mainImg") {
1;
let file = e.target.files[0] ? e.target.files[0] : "";
if (file) {
let extension = file.name.substr(file.name.lastIndexOf(".") + 1);
if (validExtensions.includes(extension)) {
setTempImg(URL.createObjectURL(file));
setstate({
...state,
image: file
});
if (hasAlpha(URL.createObjectURL(file))) {
alert(hasAlpha(URL.createObjectURL(file)));
} else {
alert("error");
}
} else {
setstate({
...state,
image: ""
});
}
} else {
setstate({
...state,
image: ""
});
setTempImg("");
}
}
};

I am here from your Google Docs bug. I have already sent a proposal to you. I tested this code. If it doesn't work in your project, it means another bug exists in your React project. To solve those bugs I need to see your whole react component code.
function hasAlpha(file) {
return new Promise((resolve, reject) => {
const img = new Image()
// create image from file
img.src = URL.createObjectURL(file)
img.onerror = reject
img.onload = () => {
// create canvas
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.width = img.width
canvas.height = img.height
ctx.drawImage(img, 0, 0)
// get image data
const data = ctx.getImageData(0, 0, canvas.width, canvas.height)
// check if image has any transparent background
const hasTransparent = [...data.data].some((value, index) => {
return index % 4 === 3 && value < 255
})
return hasTransparent ? resolve(true) : resolve(false)
}
})}
You have to wait before hasAlpha() resolve or reject. So, you should call await hasAlpha(file) and wrap entire call with try catch. If promise rejected you can access it in catch block.
try {
if(await hasAlpha(file)) {
// promise resloved, image is transparent
} else {
// promise resloved, image is not transparent
}
} catch (e) {
// promise rejected
}

Related

face-api conflicting with tensorflow-js

I'm using face-api.js Javascript API to develop a web app that user uploads her/his picture and we want to detect faces in the picture.
this is my HTML codes:
<input type="file" id="user_pic" accept="image/x-png,image/gif,image/jpeg">
<img src="images/250x250.webp" id="preview" alt="">
<canvas id="canvas"></canvas>
<script src="scripts/tfjs.js"></script>
<script src="scripts/face-api.min.js"></script>
<script src="scripts/index.js"></script>
and following code are what I wrote to face detection:
const model = tf.loadLayersModel('./web_model/vgg_model.json')
const user_pic = document.getElementById('user_pic')
const preview = document.getElementById('preview')
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
window.onload = function() {
canvas.width = preview.width;
canvas.height = preview.height;
ctx.drawImage(preview, 0, 0);
};
preview.onclick = () => user_pic.click()
const MODEL_URL = '../faceapi_models'
Promise.all([
faceapi.nets.ssdMobilenetv1.loadFromUri(MODEL_URL),
faceapi.nets.faceRecognitionNet.loadFromUri(MODEL_URL),
faceapi.nets.faceLandmark68Net.loadFromUri(MODEL_URL),])
.then((val) => {
console.log('val')
})
.catch((err) => {
console.log('err')
})
user_pic.addEventListener('change', () => {
const reader = new FileReader()
reader.onload = (e) => {
const img = new Image();
img.onload = function() {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
};
img.src = e.target.result;
}
reader.readAsDataURL(user_pic.files[0]);
detectFaces(user_pic.files[0])
})
async function detectFaces(input) {
let imgURL = URL.createObjectURL(input)
const imgElement = new Image()
imgElement.src = imgURL
const results = await faceapi.detectAllFaces(imgElement)
// .withFaceLandmarks()
// .withFaceExpressions()
.then(results => {
if (Array.isArray(results) && results.forEach) {
results.forEach(result => {
console.log(result)
const { x, y, width, height } = result.box;
ctx.lineWidth = 3;
ctx.strokeRect(x, y, width, height);
});
} else {
console.error('Results is not an array or does not have a forEach function.');
}
});
}
So far I have only used face-api.min.js file and all things work fine and after selecting image File , face is recognized. But as soon as I added tfjs.js file to use const model = tf.loadLayersModel('./web_model/vgg_model.json') method I got new following Errors:
Uncaught (in promise) Error: SsdMobilenetv1 - load model before inference
And after a few seonds this error shown in console :
Uncaught (in promise) TypeError: Og(...).platform.isTypedArray is not a function
What is problem ?

Oracle Apex - BLOB to jpg

I'm trying to pass a jpg that I have stored in a table as a blob to the following javascript code:
class ImageLoader {
constructor(imageWidth, imageHeight) {
this.canvas = document.createElement('canvas');
this.canvas.width = imageWidth;
this.canvas.height = imageHeight;
this.ctx = this.canvas.getContext('2d');
}
async getImageData(url) {
await this.loadImageAsync(url);
const imageData = this.ctx.getImageData(0, 0, this.canvas.width, this.canvas.height);
return imageData;
}
loadImageAsync(url) {
return new Promise((resolve, reject) => {
this.loadImageCb(url, () => {
resolve();
});
});
}
loadImageCb(url, cb) {
loadImage(
url,
img => {
if (img.type === 'error') {
throw `Could not load image: ${url}`;
} else {
// load image data onto input canvas
this.ctx.drawImage(img, 0, 0)
//console.log(`image was loaded`);
window.setTimeout(() => { cb(); }, 0);
}
},
{
maxWidth: this.canvas.width,
maxHeight: this.canvas.height,
cover: true,
crop: true,
canvas: true,
crossOrigin: 'Anonymous'
}
);
}
}
I've tried get APEX_UTIL.GET_BLOB_FILE_SRC, but then the javascript code throws the error "Could not load image".
I then to use the following procedure:
create or replace PROCEDURE get_file (p_file_name IN VARCHAR2) IS
l_blob_content UPLOADED_IMAGES.blob_content%TYPE;
l_mime_type UPLOADED_IMAGES.mime_type%TYPE;
BEGIN
SELECT blob_content,
mime_type
INTO l_blob_content,
l_mime_type
FROM UPLOADED_IMAGES
WHERE filename = p_file_name;
sys.HTP.init;
sys.OWA_UTIL.mime_header(l_mime_type, FALSE);
sys.HTP.p('Content-Length: ' || DBMS_LOB.getlength(l_blob_content));
sys.HTP.p('Content-Disposition: filename="' || p_file_name || '"');
sys.OWA_UTIL.http_header_close;
sys.WPG_DOCLOAD.download_file(l_blob_content);
apex_application.stop_apex_engine;
EXCEPTION
WHEN apex_application.e_stop_apex_engine
THEN RAISE;
WHEN OTHERS THEN
HTP.p('Whoops');
END;
Still the same error "Could not load image" and a new error "Whoops Status:204 No Content X-Content-Type-Options:nosniff X-Xss-Protection:1; mode=block Referrer-Policy:strict-origin Cache-Control:no-store Pragma:no-cache Expires:Sun, 27 Jul 1997 13:00:00 GMT X-Frame-Options:SAMEORIGIN".
So I'm not sure what I'm doing wrong or how to better go about doing this right.
Update:
I've now tried "blob2clobbase64", but that doesn't seem to anything:
declare
l_image_clob clob;
l_image_blob blob;
begin
select BLOB_CONTENT
into l_image_blob
from UPLOADED_IMAGES
where FILENAME = :P1_IMAGES;
l_image_clob := apex_web_service.blob2clobbase64(
p_blob => l_image_blob
);
apex_json.open_object;
apex_json.write('imageBase64', l_image_clob );
apex_json.close_object;
end;
The code I'm using for image loading:
const imageSize = 224;
const imageBLOB = new Image();
// Load image.
apex.server.process(
"get_file",
{},
{
success: function(data) {
imageBLOB.src = 'data:image/jpeg;base64,' + data.imageBase64;
const imageLoader = new ImageLoader(imageSize, imageSize);
const imageData = await imageLoader.getImageData(imageBLOB);
}
}
);
I got it to work. I ended up using the "blob2clobbase64" process and instead of using the ImageLoader class and instead used getImageData from the canvas. The PL/SQL is the same but the JavaScript is different:
const imageSize = 224;
var newImageDate;
function returnImageData(imageData){
return newImageDate = imageData;
}
async function runImageExample(){
apex.server.process(
"get_image", {}, {
success: async function(data) {
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var imageBLOB = new Image();
imageBLOB.onload = function() {
imageBLOB.crossOrigin = "Anonymous";
ctx.drawImage(imageBLOB, 0, 0, imageSize, imageSize);
var imgData = ctx.getImageData(0, 0, imageSize, imageSize);
returnImageData(imgData.data);
};
imageBLOB.src = 'data:image/jpeg;base64,' + data.photoBase64;
}
}
);
}

JavaScript image compression recursion

I have the following function where user can upload an images and then compress them. The problem here is that when I console.log(e.target) inside the image.onload function, it displays it continuously in the console, meaning it is in a recursion and it freezes my app and it cannot do anything else.
This compression method I have taken from the following YouTube video and tried to adopt to what I have.
https://www.youtube.com/watch?v=bXf_UdyDzSA&ab_channel=Cod%C3%BACommunity
function addImageToForm(e) {
firebase.auth().onAuthStateChanged(function (user) {
if (user) {
let files = e.target.files;
if (numberOfImages + files.length > 4) {
alert("You can only upload at most 4 files!");
return;
}
numberOfImages += files.length;
for (let i = 0; i < files.length; i++) {
let file = files[i];
if (file) {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.addEventListener("load", function (e) {
console.log(this);
let imageFile = e.target;
let divDocument = document.createElement("div");
let image = document.createElement("img");
divDocument.setAttribute("class", "id-document");
image.setAttribute("class", "image-preview");
image.setAttribute(
"style",
"width: inherit; height: inherit; border-radius: 20px;"
);
image.setAttribute("src", imageFile.result);
image.onload = function (e) {
let canvas = document.createElement("canvas");
let MAX_WIDTH = 200;
let scaleSize = MAX_WIDTH / e.target.width;
canvas.width = MAX_WIDTH;
canvas.height = e.target.height * scaleSize;
let ctx = canvas.getContext("2d");
ctx.drawImage(e.target, 0, 0, canvas.width, canvas.height);
console.log(e.target);
let srcEncoded = ctx.canvas.toDataURL(e.target, "image/jpeg");
image.setAttribute("src", srcEncoded);
}
divDocument.appendChild(image);
rowOfPhotos.appendChild(divDocument);
});
const reference = firebase
.storage()
.ref(`${user.displayName}/game_images/` + file.name);
reference
.put(file)
.then((snapshot) => snapshot.ref.getDownloadURL())
.then((url) => {
imagesArray.push(url);
});
} else {
image.style.display = null;
}
}
} else {
console.log("Not logged in");
}
});
}
Does anybody see where the problem is?
It's because, you change image src in onload function
image.setAttribute("src", srcEncoded);
Every time, image src is changed, onload function will be called.

Get width height of remote image from url

So the alert gives undefined values for the width and height. I think the w and h values of the image from the img.onload calculation is not being passed to the values to return, or it may be returning w and h before the onload calculates them:
function getMeta(url){
var w; var h;
var img=new Image;
img.src=url;
img.onload=function(){w=this.width; h=this.height;};
return {w:w,h:h}
}
// "http://snook.ca/files/mootools_83_snookca.png" //1024x678
// "http://shijitht.files.wordpress.com/2010/08/github.png" //128x128
var end = getMeta("http://shijitht.files.wordpress.com/2010/08/github.png");
var w = end.w;
var h = end.h;
alert(w+'width'+h+'height');
How can I have the alert show the correct width and height?
http://jsfiddle.net/YtqXk/
Get image size with JavaScript
In order to read the data from an image you'll need to make sure it's first loaded. Here's a callback-based approach and two promise-based solutions:
Callback
const getMeta = (url, cb) => {
const img = new Image();
img.onload = () => cb(null, img);
img.onerror = (err) => cb(err);
img.src = url;
};
// Use like:
getMeta("https://i.stack.imgur.com/qCWYU.jpg", (err, img) => {
console.log(img.naturalWidth, img.naturalHeight);
});
Using the load Event listener (Promise):
const getMeta = (url) =>
new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = (err) => reject(err);
img.src = url;
});
// Usage example:
;(async() => {
const img = await getMeta('https://i.stack.imgur.com/qCWYU.jpg');
console.dir(img.naturalHeight + ' ' + img.naturalWidth);
})();
Using HTMLImageElement.decode() (Promise)
const getMeta = async (url) => {
const img = new Image();
img.src = url;
await img.decode();
return img
};
// Usage example:
getMeta('https://i.stack.imgur.com/qCWYU.jpg').then(img => {
console.dir(img.naturalHeight +' '+ img.naturalWidth);
});
MDN Docs: HTMLImageElement
Just pass a callback as argument like this:
function getMeta(url, callback) {
const img = new Image();
img.src = url;
img.onload = function() { callback(this.width, this.height); }
}
getMeta(
"http://snook.ca/files/mootools_83_snookca.png",
(width, height) => { alert(width + 'px ' + height + 'px') }
);
ES6
Using async/await you can do below getMeta function in sequence-like way and you can use it as follows (which is almost identical to code in your question (I add await keyword and change variable end to img, and change var to let keyword). You need to run getMeta by await only from async function (run).
function getMeta(url) {
return new Promise((resolve, reject) => {
let img = new Image();
img.onload = () => resolve(img);
img.onerror = () => reject();
img.src = url;
});
}
async function run() {
let img = await getMeta("http://shijitht.files.wordpress.com/2010/08/github.png");
let w = img.width;
let h = img.height;
size.innerText = `width=${w}px, height=${h}px`;
size.appendChild(img);
}
run();
<div id="size" />
Rxjs
const { race, fromEvent, map, mergeMap, of } = rxjs;
function getMeta(url) {
return of(url).pipe(
mergeMap((path) => {
const img = new Image();
let load = fromEvent(img, 'load').pipe(map(_=> img))
let error = fromEvent(img, 'error').pipe(mergeMap((err) => throwError(() => err)));
img.src = path;
return race(load, error);
})
);
}
let url = "http://shijitht.files.wordpress.com/2010/08/github.png";
getMeta(url).subscribe(img=> {
let w = img.width;
let h = img.height;
size.innerText = `width=${w}px, height=${h}px`;
size.appendChild(img);
}, e=> console.log('Load error'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.5.2/rxjs.umd.min.js" integrity="sha512-wBEi/LQM8Pi08xK2jwHJNCiHchHnfcJao0XVQvkTGc91Q/yvC/6q0xPf+qQr54SlG8yRbRCA8QDYrA98+0H+hg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div id="size" />
The w and h variables in img.onload function are not in the same scope with those in the getMeta() function. One way to do it, is as follows:
Fiddle: http://jsfiddle.net/ppanagi/28UES/2/
function getMeta(varA, varB) {
if (typeof varB !== 'undefined') {
alert(varA + ' width ' + varB + ' height');
} else {
var img = new Image();
img.src = varA;
img.onload = getMeta(this.width, this.height);
}
}
getMeta("http://snook.ca/files/mootools_83_snookca.png");
Get image size with jQuery
(depending on which formatting method is more suitable for your preferences):
function getMeta(url){
$('<img/>',{
src: url,
on: {
load: (e) => {
console.log('image size:', $(e.target).width(), $(e.target).height());
},
}
});
}
or
function getMeta(url){
$('<img/>',{
src: url,
}).on({
load: (e) => {
console.log('image size:', $(e.target).width(), $(e.target).height());
},
});
}
You will can try package.
import getImageSize from 'image-size-from-url';
const {width, height} = await getImageSize('URL');

Check image width and height before upload with Javascript

I have a JPS with a form in which a user can put an image:
<div class="photo">
<div>Photo (max 240x240 and 100 kb):</div>
<input type="file" name="photo" id="photoInput" onchange="checkPhoto(this)"/>
</div>
I have written this js:
function checkPhoto(target) {
if(target.files[0].type.indexOf("image") == -1) {
document.getElementById("photoLabel").innerHTML = "File not supported";
return false;
}
if(target.files[0].size > 102400) {
document.getElementById("photoLabel").innerHTML = "Image too big (max 100kb)";
return false;
}
document.getElementById("photoLabel").innerHTML = "";
return true;
}
which works fine to check file type and size. Now I want to check image width and height but I cannot do it.
I have tried with target.files[0].width but I get undefined. With other ways I get 0.
Any suggestions?
The file is just a file, you need to create an image like so:
var _URL = window.URL || window.webkitURL;
$("#file").change(function (e) {
var file, img;
if ((file = this.files[0])) {
img = new Image();
var objectUrl = _URL.createObjectURL(file);
img.onload = function () {
alert(this.width + " " + this.height);
_URL.revokeObjectURL(objectUrl);
};
img.src = objectUrl;
}
});
Demo: http://jsfiddle.net/4N6D9/1/
I take it you realize this is only supported in a few browsers. Mostly firefox and chrome, could be opera as well by now.
P.S. The URL.createObjectURL() method has been removed from the MediaStream interface. This method has been deprecated in 2013 and superseded by assigning streams to HTMLMediaElement.srcObject. The old method was removed because it is less safe, requiring a call to URL.revokeOjbectURL() to end the stream. Other user agents have either deprecated (Firefox) or removed (Safari) this feature feature.
For more information, please refer here.
In my view the perfect answer you must required is
var reader = new FileReader();
//Read the contents of Image File.
reader.readAsDataURL(fileUpload.files[0]);
reader.onload = function (e) {
//Initiate the JavaScript Image object.
var image = new Image();
//Set the Base64 string return from FileReader as source.
image.src = e.target.result;
//Validate the File Height and Width.
image.onload = function () {
var height = this.height;
var width = this.width;
if (height > 100 || width > 100) {
alert("Height and Width must not exceed 100px.");
return false;
}
alert("Uploaded image has valid Height and Width.");
return true;
};
};
I agree. Once it is uploaded to somewhere the user's browser can access then it is pretty easy to get the size. As you need to wait for the image to load you'll want to hook into the onload event for img.
Updated example:
// async/promise function for retrieving image dimensions for a URL
function imageSize(url) {
const img = document.createElement("img");
const promise = new Promise((resolve, reject) => {
img.onload = () => {
// Natural size is the actual image size regardless of rendering.
// The 'normal' `width`/`height` are for the **rendered** size.
const width = img.naturalWidth;
const height = img.naturalHeight;
// Resolve promise with the width and height
resolve({width, height});
};
// Reject promise on error
img.onerror = reject;
});
// Setting the source makes it start downloading and eventually call `onload`
img.src = url;
return promise;
}
// How to use in an async function
(async() => {
const imageUrl = 'http://your.website.com/userUploadedImage.jpg';
const imageDimensions = await imageSize(imageUrl);
console.info(imageDimensions); // {width: 1337, height: 42}
})();
Older example:
var width, height;
var img = document.createElement("img");
img.onload = function() {
// `naturalWidth`/`naturalHeight` aren't supported on <IE9. Fallback to normal width/height
// The natural size is the actual image size regardless of rendering.
// The 'normal' width/height are for the **rendered** size.
width = img.naturalWidth || img.width;
height = img.naturalHeight || img.height;
// Do something with the width and height
}
// Setting the source makes it start downloading and eventually call `onload`
img.src = "http://your.website.com/userUploadedImage.jpg";
This is the easiest way to check the size
let img = new Image()
img.src = window.URL.createObjectURL(event.target.files[0])
img.onload = () => {
alert(img.width + " " + img.height);
}
Check for specific size. Using 100 x 100 as example
let img = new Image()
img.src = window.URL.createObjectURL(event.target.files[0])
img.onload = () => {
if(img.width === 100 && img.height === 100){
alert(`Nice, image is the right size. It can be uploaded`)
// upload logic here
} else {
alert(`Sorry, this image doesn't look like the size we wanted. It's
${img.width} x ${img.height} but we require 100 x 100 size image.`);
}
}
Attach the function to the onchange method of the input type file /onchange="validateimg(this)"/
function validateimg(ctrl) {
var fileUpload = ctrl;
var regex = new RegExp("([a-zA-Z0-9\s_\\.\-:])+(.jpg|.png|.gif)$");
if (regex.test(fileUpload.value.toLowerCase())) {
if (typeof (fileUpload.files) != "undefined") {
var reader = new FileReader();
reader.readAsDataURL(fileUpload.files[0]);
reader.onload = function (e) {
var image = new Image();
image.src = e.target.result;
image.onload = function () {
var height = this.height;
var width = this.width;
if (height < 1100 || width < 750) {
alert("At least you can upload a 1100*750 photo size.");
return false;
}else{
alert("Uploaded image has valid Height and Width.");
return true;
}
};
}
} else {
alert("This browser does not support HTML5.");
return false;
}
} else {
alert("Please select a valid Image file.");
return false;
}
}
const ValidateImg = (file) =>{
let img = new Image()
img.src = window.URL.createObjectURL(file)
img.onload = () => {
if(img.width === 100 && img.height ===100){
alert("Correct size");
return true;
}
alert("Incorrect size");
return true;
}
}
I think this may be the simplest for uploads if you want to use it other functions.
async function getImageDimensions(file) {
let img = new Image();
img.src = URL.createObjectURL(file);
await img.decode();
let width = img.width;
let height = img.height;
return {
width,
height,
}
}
Use like
const {width, height } = await getImageDimensions(file)
Suppose you were storing an image for Tiger taken in Kenya. So you could use it like to upload to cloud storage and then store photo information.
const addImage = async (file, title, location) => {
const { width, height } = await getImageDimensions(file)
const url = await uploadToCloudStorage(file) // returns storage url
await addToDatabase(url, width, height, title, location)
}
function validateimg(ctrl) {
var fileUpload = $("#txtPostImg")[0];
var regex = new RegExp("([a-zA-Z0-9\s_\\.\-:])+(.jpg|.png|.gif)$");
if (regex.test(fileUpload.value.toLowerCase())) {
if (typeof (fileUpload.files) != "undefined") {
var reader = new FileReader();
reader.readAsDataURL(fileUpload.files[0]);
reader.onload = function (e) {
var image = new Image();
image.src = e.target.result;
image.onload = function () {
var height = this.height;
var width = this.width;
console.log(this);
if ((height >= 1024 || height <= 1100) && (width >= 750 || width <= 800)) {
alert("Height and Width must not exceed 1100*800.");
return false;
}
alert("Uploaded image has valid Height and Width.");
return true;
};
}
} else {
alert("This browser does not support HTML5.");
return false;
}
} else {
alert("Please select a valid Image file.");
return false;
}
}
You can do the steps for previewing the image without showing it which is supported on all browsers. Following js code shows you how to check the width and height :
var file = e.target.files[0];
if (/\.(jpe?g|png|gif)$/i.test(file.name)) {
var reader = new FileReader();
reader.addEventListener("load", function () {
var image = new Image();
image.src = this.result as string;
image.addEventListener('load', function () {
console.log(`height: ${this.height}, width: ${this.width}`);
});
}, false);
reader.readAsDataURL(file);
}
Based on Mozilla docs:
The readAsDataURL method is used to read the contents of the specified
Blob or File. When the read operation is finished, the readyState
becomes DONE, and the loadend is triggered. At that time, the result
attribute contains the data as a data: URL representing the file's
data as a base64 encoded string.
And the browser compatibility is listed too.
In my case, I needed to also prevent the form from being submited, so here is the solution that worked for me.
The preventDefault will stop the form action, then we check the size and dimensions of the image in the onload function.
If all good, we allow the submit.
As the submit button gets disabled if a user still tries to submit the form with an invalid image, I also had to re-able the submit button once a valid image is inputted.
const validateMaxImageFileSize = (e) => {
e.preventDefault();
const el = $("input[type='file']")[0];
if (el.files && el.files[0]) {
const file = el.files[0];
const maxFileSize = 5242880; // 5 MB
const maxWidth = 1920;
const maxHeight = 1080;
const img = new Image();
img.src = window.URL.createObjectURL(file);
img.onload = () => {
if (file.type.match('image.*') && file.size > maxFileSize) {
alert('The selected image file is too big. Please choose one that is smaller than 5 MB.');
} else if (file.type.match('image.*') && (img.width > maxWidth || img.height > maxHeight)) {
alert(`The selected image is too big. Please choose one with maximum dimensions of ${maxWidth}x${maxHeight}.`);
} else {
e.target.nodeName === 'INPUT'
? (e.target.form.querySelector("input[type='submit']").disabled = false)
: e.target.submit();
}
};
}
};
$('form.validate-image-size').on('submit', validateMaxImageFileSize);
$("form.validate-image-size input[type='file']").on('change', validateMaxImageFileSize);
function uploadfile(ctrl) {
var validate = validateimg(ctrl);
if (validate) {
if (window.FormData !== undefined) {
ShowLoading();
var fileUpload = $(ctrl).get(0);
var files = fileUpload.files;
var fileData = new FormData();
for (var i = 0; i < files.length; i++) {
fileData.append(files[i].name, files[i]);
}
fileData.append('username', 'Wishes');
$.ajax({
url: 'UploadWishesFiles',
type: "POST",
contentType: false,
processData: false,
data: fileData,
success: function(result) {
var id = $(ctrl).attr('id');
$('#' + id.replace('txt', 'hdn')).val(result);
$('#imgPictureEn').attr('src', '../Data/Wishes/' + result).show();
HideLoading();
},
error: function(err) {
alert(err.statusText);
HideLoading();
}
});
} else {
alert("FormData is not supported.");
}
}

Categories