How do I block uploads that lack "DateTimeOriginal" exif data with Fine Uploader? - fine-uploader

I have an app where having the DateTimeOriginal time stamp on photos are absolutely necessary. Is there a way for me to stop uploading and display a message using Fine Uploader?

I've never heard of the "taken-at" tag, and I don't believe this is a standard field. The rest of this answer assumes you really do want to focus on this tag, but even if you don't you can make a simple change in the source code below to focus on another EXIF tag instead.
One approach is to check each file in an onSubmit callback handler and simply reject the file is it does not contain a "taken-at" field. The following example utilizes the exif-js library to parse an image file's EXIF data:
var uploader = new qq.FineUploader({
callbacks: {
onSubmit: function(id) {
var blob = this.getFile(id)
return new Promise(function(resolve, reject) {
EXIF.getData(blob, function() {
var takenAt = EXIF.getTag(this, 'taken-at')
if (takenAt) {
resolve()
}
else {
reject()
}
})
})
}
}
})

Related

Fine Upload No File to upload

I am using FineUploader in my form using this : http://docs.fineuploader.com/branch/master/features/forms.html.
The problem is that, in my form file field is optional.
If I send the form I have this and the form doesn't proceed:
Error On submit
And my js code :
var uploader = new qq.FineUploader({
element: document.getElementById('my-uploader'),
maxConnections:1,
callbacks: {
onAllComplete: function(id, fileName, responseJSON) {
location.reload();
}
}
});
Fine Uploader is a file upload library. As such, you must provide it with files to upload. It is not a form submission library, and will not submit a form unless a file is involved. If you would like to submit a form without a file, you will need to omit attaching Fine Uploader to the form. Your best bet in this case is to allow the file to be sent independent of the form submit.
You can check if there are 0 files: in that case, don't trigger fineUploader "uploadStoredFiles" method. E.g.
var fineUploaderTrigger = jQuery('<div id="fine-uploader"></div>');
fineUploaderTrigger.fineUploader({
template: 'qq-template-manual-trigger',
autoUpload: false, /* important */
[...]
});
var submitButton = $('#submit');
// Trigger upload
submitButton.on('click', function (e) {
e.preventDefault();
// go on also if there are no files to upload
if ($('.qq-upload-list li').length > 0) {
$('#fine-uploader-manual-trigger').fineUploader('uploadStoredFiles');
} else {
submitButton.off('click');
submitButton.click();
}
});

Remove previews from dropzone after success

I want to rollback the original dropzone with its message "drop files here" after the success event of dropzone or after the complete event of dropzone.
I don't want to see the preview after success or complete.
This is my dropzone script:
Dropzone.options.myAwesomeDropzone = {
paramName: "file", // The name that will be used to transfer the file
maxFilesize: 2, // MB
parallelUploads: 1,
success: function(file, response) {
var imageSrc = response;
$(".img-responsive").attr('src', imageSrc);
if (imageSrc == '/assets/images/offerfeatimg.jpg') {
$(".removebutton").hide();
} else {
$(".removebutton").show();
}
}
};
Leveraging #kkthxby3 's idea, the innerHTML for the thumbnail can be cleared in the success method using the following code:
success: function (file, response) {
file.previewElement.innerHTML = "";
}
The beauty of this approach is that it clears the thumbnail without firing the removedFile event.
This leaves the following html in the dom where the thumbnail was:
<div class="dz-preview dz-processing dz-image-preview dz-complete"></div>
but as you can see, the div above which is responsible for displaying the thumbnail is now empty.
Another approach is to remove even the enclosing div that wraps the thumbnail along with it's contents. This approach can be accomplished with the following code in the success method and leaves no trace of the thumbnail in the dom:
success: function (file, response) {
file.previewElement.parentNode.removeChild(file.previewElement);
}
Enjoy.
only need call method removeFile in success function
success: function (file, response) {
this.removeFile(file);
}
check doc dropzone
For me the easiest way to make the file preview not appear is with css.
dz-preview and dz-file-preview are a couple classes in the outer div of the preview html generated by the default template.
.dz-preview, .dz-file-preview {
display: none;
}
I also told it to not create thumbnails in the Dropzone.options.
Dropzone.options.myDropzone = {
paramName: "file",
maxFilesize: 2, // MB
url: 'post_image',
createImageThumbnails: false, // NO THUMBS!
init: function () {
this.on('sending', dz_sending),
this.on('success', dz_success),
this.on('error', dz_error),
this.on('complete', dz_complete) // Once it's done...
}
The template still generates all the preview html though. So in my 'complete' function dz_complete I delete it all.
function dz_complete(file) {
$('.dz-preview').remove(); // ...delete the template gen'd html.
}
Just an fyi...
The method 'removeAllFiles' is not necessarily the prime choice. Which is the same as 'removeFile(file)'.
I have an event handler for dropZone's 'removedfile' event... I'm using it to send a server message to delete the respective file from the server (should a user delete the thumbnail after it's been uploaded). Using the method 'removeAllFiles' (as well as the individualized 'removeFile(file)') fires the event 'removedfile' which deletes the uploaded images in addition to clearing the thumbnails.
So one could add some finessing around this but in the reality of it the method is not correct.
Looking through the api for Dropzone I am not seeing an API call to simply reset or clear the thumbnails... The method 'disable()' will clear the stored file names and what not but does not clear the thumbnails... Seems dropzoneJS is actually missing a critical API call to be honest.
My work around is to manually reset the containing div for dropzone:
document.getElementById("divNameWhereDropzoneClassIs").innerHTML = ""
This clears the thumbnails without firing off the event 'removedfile' which is supposed to be used for deleting an image from the server...
The easiest thing is to call the dropzone removeFile() method, using an event listener for the success event.
Dropzone.options.myAwesomeDropzone = {
paramName: "file",
maxFilesize: 2,
parallelUploads: 1,
init: function() {
this.on("success", function(file, response) {
var imageSrc = response;
$(".img-responsive").attr('src', imageSrc);
if(imageSrc == '/assets/images/offerfeatimg.jpg') {
$(".removebutton").hide();
} else {
$(".removebutton").show();
}
this.removeFile(file); // This line removes the preview
})
}
};
I was using file.previewElement.remove(), works fine in Chrome but does not work in IE.
Then I tried this.removeFile(file), but it didn't work for me.
After that i tried file.previewElement.innerHTML = "" which works in both Chrome and IE but it leaves an extra div where the preview elements were.
So this one works better for me...
success: function (file, response) {
file.previewElement.outerHTML = "";
}
If you want to remove an added file from the dropzone, you can call .removeFile(file). This method also triggers the removedfile event.
Here’s an example that would automatically remove a file when it’s finished uploading:
myDropzone.on("complete", function(file) {
myDropzone.removeFile(file);
});
If you want to remove all files, simply use .removeAllFiles(). Files that are in the process of being uploaded won’t be removed. If you want files that are currently uploading to be canceled, call .removeAllFiles(true) which will cancel the uploads.
100% Tested and Working:
$('#preview_image_container .dz-preview .dz-remove').attr('id','removeFile');
document.getElementById("removeFile").click();

Removing images from a page before they load

I'm developing an extension using Crossrider and want to block certain images before they load. Currently, I'm trying in the extension.js file using the code below, but it only removes them after they have loaded and does't catch AJAX loaded images. How can I do this with Crossrider?
appAPI.ready(function($) {
$('img').remove();
});
This is best achieved in the background scope using the appAPI.webRequest.onRequest.addListener method to catch image requests and block them before they load. For example:
appAPI.ready(function() {
// The list of image file types you wish to block
var fileTypeBlockList = 'jpg|gif|svg';
appAPI.webRequest.onRequest.addListener(function(details) {
if (details.method == "GET" &&
details.requestUrl.match(new RegExp('.'+fileTypeBlockList+'$','i')) {
return { cancel: true };
}
});
});
[Disclosure: I am a Crossrider employee]

fineuploader - Read file dimensions / Validate by resolution

I would like to validate by file dimensions (resolution).
on the documentation page there is only information regarding file name and size, nothing at all in the docs about dimensions, and I also had no luck on Google.
The purpose of this is that I don't want users to upload low-res photos to my server. Thanks.
As Ray Nicholus had suggested, using the getFile method to get the File object and then use that with the internal instance object qq.ImageValidation to run fineuploader's validation on the file. A promise must be return because this proccess is async.
function onSubmit(e, id, filename){
var promise = validateByDimensions(id, [1024, 600]);
return promise;
}
function validateByDimensions(id, dimensionsArr){
var deferred = new $.Deferred(),
file = uploaderElm.fineUploader('getFile', id),
imageValidator = new qq.ImageValidation(file, function(){}),
result = imageValidator.validate({
minWidth : dimensionsArr[0],
minHeight : dimensionsArr[1]
});
result.done(function(status){
if( status )
deferred.reject();
else
deferred.resolve();
});
return deferred.promise();
}
Remained question:
Now I wonder how to show the thumbnail of the image that was rejected, while not uploading it to the server, the UI could mark in a different color as an "invalid image", yet the user could see which images we valid and which weren't...
- Update - (regarding the question above)
While I do not see how I could have the default behavior of a thumbnail added to the uploader, but not being uploaded, but there is a way to generate thumbnail manually, like so:
var img = new Image();
uploaderElm.fineUploader("drawThumbnail", id, img, 200, false);
but then I'll to create an item to be inserted to qq-upload-list myself, and handle it all myself..but still it's not so hard.
Update (get even more control over dimensions validation)
You will have to edit (currently) the qq.ImageValidation function to expose outside the private function getWidthHeight. just change that function deceleration to:
this.getWidthHeight = function(){
Also, it would be even better to change the this.validate function to:
this.validate = function(limits) {
var validationEffort = new qq.Promise();
log("Attempting to validate image.");
if (hasNonZeroLimits(limits)) {
this.getWidthHeight().done(function(dimensions){
var failingLimit = getFailingLimit(limits, dimensions);
if (failingLimit) {
validationEffort.failure({ fail:failingLimit, dimensions:dimensions });
}
else {
validationEffort.success({ dimensions:dimensions });
}
}, validationEffort.success);
}
else {
validationEffort.success();
}
return validationEffort;
};
So you would get the fail reason, as well as the dimensions. always nice to have more control.
Now, we could write the custom validation like this:
function validateFileDimensions(dimensionsLimits){
var deferred = new $.Deferred(),
file = this.holderElm.fineUploader('getFile', id),
imageValidator = new qq.ImageValidation(file, function(){});
imageValidator.getWidthHeight().done(function(dimensions){
var minWidth = dimensions.width > dimensionsLimits.width,
minHeight = dimensions.height > dimensionsLimits.height;
// if min-width or min-height satisfied the limits, then approve the image
if( minWidth || minHeight )
deferred.resolve();
else
deferred.reject();
});
return deferred.promise();
}
This approach gives much more flexibility. For example, you would want to have different validation for portrait images than landscape ones, you could easily identify the image orientation and run your own custom code to do whatever.

Loading images with ajax (in rails) [duplicate]

I want to load external images on my page asynchronously using jQuery and I have tried the following:
$.ajax({
url: "http://somedomain.com/image.jpg",
timeout:5000,
success: function() {
},
error: function(r,x) {
}
});
But it always returns error, is it even possible to load image like this?
I tried to use .load method and it works but I have no idea how I can set timeout if the image is not available (404). How can I do this?
No need for ajax. You can create a new image element, set its source attribute and place it somewhere in the document once it has finished loading:
var img = $("<img />").attr('src', 'http://somedomain.com/image.jpg')
.on('load', function() {
if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) {
alert('broken image!');
} else {
$("#something").append(img);
}
});
IF YOU REALLY NEED TO USE AJAX...
I came accross usecases where the onload handlers were not the right choice. In my case when printing via javascript. So there are actually two options to use AJAX style for this:
Solution 1
Use Base64 image data and a REST image service. If you have your own webservice, you can add a JSP/PHP REST script that offers images in Base64 encoding. Now how is that useful? I came across a cool new syntax for image encoding:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhE..."/>
So you can load the Image Base64 data using Ajax and then on completion you build the Base64 data string to the image! Great fun :). I recommend to use this site http://www.freeformatter.com/base64-encoder.html for image encoding.
$.ajax({
url : 'BASE64_IMAGE_REST_URL',
processData : false,
}).always(function(b64data){
$("#IMAGE_ID").attr("src", "data:image/png;base64,"+b64data);
});
Solution2:
Trick the browser to use its cache. This gives you a nice fadeIn() when the resource is in the browsers cache:
var url = 'IMAGE_URL';
$.ajax({
url : url,
cache: true,
processData : false,
}).always(function(){
$("#IMAGE_ID").attr("src", url).fadeIn();
});
However, both methods have its drawbacks: The first one only works on modern browsers. The second one has performance glitches and relies on assumption how the cache will be used.
cheers,
will
Using jQuery you may simply change the "src" attribute to "data-src". The image won't be loaded. But the location is stored with the tag. Which I like.
<img class="loadlater" data-src="path/to/image.ext"/>
A Simple piece of jQuery copies data-src to src, which will start loading the image when you need it. In my case when the page has finished loading.
$(document).ready(function(){
$(".loadlater").each(function(index, element){
$(element).attr("src", $(element).attr("data-src"));
});
});
I bet the jQuery code could be abbreviated, but it is understandable this way.
$(<img />).attr('src','http://somedomain.com/image.jpg');
Should be better than ajax because if its a gallery and you are looping through a list of pics, if the image is already in cache, it wont send another request to server. It will request in the case of jQuery/ajax and return a HTTP 304 (Not modified) and then use original image from cache if its already there. The above method reduces an empty request to server after the first loop of images in the gallery.
You can use a Deferred objects for ASYNC loading.
function load_img_async(source) {
return $.Deferred (function (task) {
var image = new Image();
image.onload = function () {task.resolve(image);}
image.onerror = function () {task.reject();}
image.src=source;
}).promise();
}
$.when(load_img_async(IMAGE_URL)).done(function (image) {
$(#id).empty().append(image);
});
Please pay attention: image.onload must be before image.src to prevent problems with cache.
If you just want to set the source of the image you can use this.
$("img").attr('src','http://somedomain.com/image.jpg');
This works too ..
var image = new Image();
image.src = 'image url';
image.onload = function(e){
// functionalities on load
}
$("#img-container").append(image);
AFAIK you would have to do a .load() function here as apposed to the .ajax(), but you could use jQuery setTimeout to keep it live (ish)
<script>
$(document).ready(function() {
$.ajaxSetup({
cache: false
});
$("#placeholder").load("PATH TO IMAGE");
var refreshId = setInterval(function() {
$("#placeholder").load("PATH TO IMAGE");
}, 500);
});
</script>
use .load to load your image. to test if you get an error ( let's say 404 ) you can do the following:
$("#img_id").error(function(){
//$(this).hide();
//alert("img not loaded");
//some action you whant here
});
careful - .error() event will not trigger when the src attribute is empty for an image.
//Puedes optar por esta solución:
var img = document.createElement('img');
img.setAttribute('src', element.source)
img.addEventListener('load', function(){
if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) {
alert('broken image!');
} else {
$("#imagenesHub").append(img);
}
});
$(function () {
if ($('#hdnFromGLMS')[0].value == 'MB9262') {
$('.clr').append('<img src="~/Images/CDAB_london.jpg">');
}
else
{
$('.clr').css("display", "none");
$('#imgIreland').css("display", "block");
$('.clrIrland').append('<img src="~/Images/Ireland-v1.jpg">');
}
});

Resources