File validation
It is quite common when you want to restrict your users from uploading files of certain sizes, types, etc. That’s where File validation comes in. Validator is just a function that receives a fileInfo
object for each uploaded file and throws an exception if the file does not meet validation requirements.
Before digging into all kinds of validation, check out this stuff:
- Allowing to upload images only
- Set widget input accept types
- Set widget preferred MIME types
- Define validators as a widget option
Simple file size check
The simplest validatior, which checks file sizes, can look like this,
widget.validators.push(function(fileInfo) {
if (fileInfo.size !== null && fileInfo.size > 1024 * 1024) {
throw new Error("fileMaximumSize");
}
});
Validation functions
It is better to wrap validators in a function that receives a constant, like a file size threshold. Such validators can then be reused by different widgets:
function maxFileSize(size) {
return function(fileInfo) {
if (fileInfo.size !== null && fileInfo.size > size) {
throw new Error("fileMaximumSize");
}
};
}
// limit file size to 1 MB
widget1.validators.push(maxFileSize(1024 * 1024));
// limit file size to 2 MB
widget2.validators.push(maxFileSize(2 * 1024 * 1024));
Automatic validation
Automatic validation means we are going to check parameters based on data attributes of an input element. For example, if your widget has the data-max-size
option enabled, we can add the maxFileSize
validatior in the following manner,
$(function() {
$('[role=uploadcare-uploader][data-max-size]').each(function() {
var widget = uploadcare.Widget(this);
widget.validators.push(maxFileSize($(this).data('maxSize')));
});
});
Common validators
Here are some common validation cases for you to consider,
Limit File Size
The example below shows how to add validation for both min and max file sizes. A validator is automatically added to each widget with data-min-size
and data-max-size
custom attributes.
function fileSizeLimit(min, max) {
return function(fileInfo) {
if (fileInfo.size === null) {
return;
}
if (min && fileInfo.size < min) {
throw new Error("fileMinimalSize");
}
if (max && fileInfo.size > max) {
throw new Error("fileMaximumSize");
}
};
}
$(function() {
$('[role=uploadcare-uploader]').each(function() {
var input = $(this);
if ( ! input.data('minSize') && ! input.data('maxSize')) {
return;
}
var widget = uploadcare.Widget(input);
widget.validators.push(fileSizeLimit(input.data('minSize'),
input.data('maxSize')));
});
});
UPLOADCARE_LOCALE_TRANSLATIONS = {
// messages for widget
errors: {
'fileMinimalSize': 'File is too small',
'fileMaximumSize': 'File is too large'
},
// messages for dialog’s error page
dialog: { tabs: { preview: { error: {
'fileMinimalSize': {
title: 'Title.',
text: 'Text.',
back: 'Back'
},
'fileMaximumSize': {
title: 'Title.',
text: 'Text.',
back: 'Back'
}
} } } }
};
<p>
<code>data-min-size="102400"</code><br>
<input type="hidden" role="uploadcare-uploader" data-min-size="102400">
</p>
<p>
<code>data-max-size="1048576"</code><br>
<input type="hidden" role="uploadcare-uploader" data-max-size="1048576">
</p>
<p>
<code>data-multiple="true" data-min-size="102400" data-max-size="1048576"</code><br>
<input type="hidden" role="uploadcare-uploader" data-multiple="true" data-min-size="102400" data-max-size="1048576">
</p>
data-min-size="102400"
data-max-size="1048576"
data-multiple="true" data-min-size="102400" data-max-size="1048576"
Restrict File Type
fileTypeLimit
is another validator that can be added to widgets with the data-file-types
custom attribute whose value is a space-separated list of allowed files extensions.
function fileTypeLimit(types) {
types = types.split(' ');
return function(fileInfo) {
if (fileInfo.name === null) {
return;
}
var extension = fileInfo.name.split('.').pop();
if (types.indexOf(extension) == -1) {
throw new Error("fileType");
}
};
}
$(function() {
$('[role=uploadcare-uploader][data-file-types]').each(function() {
var input = $(this);
var widget = uploadcare.Widget(input);
widget.validators.push(fileTypeLimit(input.data('file-types')));
});
});
UPLOADCARE_LOCALE_TRANSLATIONS = {
// messages for widget
errors: {
'fileType': 'This type of files is not allowed.'
},
// messages for dialog’s error page
dialog: { tabs: { preview: { error: {
'fileType': {
title: 'Title.',
text: 'Text.',
back: 'Back'
}
} } } }
};
<p>
<code>data-file-types="pdf doc docx"</code><br>
<input type="hidden" role="uploadcare-uploader" data-file-types="pdf doc docx">
</p>
<p>
<code>data-file-types="avi mp4 ogv mov"</code><br>
<input type="hidden" role="uploadcare-uploader" data-file-types="avi mp4 ogv mov">
</p>
data-file-types="pdf doc docx"
data-file-types="avi mp4 ogv mov"
Image Dimensions
For images, you can define the maxDimensions
validator that will be added to widgets with either data-max-width
or data-max-height
custom attributes. Please note, maxDimensions
only checks image dimensions even though it accepts any file type. You can combine it with the data-images-only
attribute to change this behavior.
function maxDimensions(width, height) {
return function(fileInfo) {
var imageInfo = fileInfo.originalImageInfo;
if (imageInfo === null) {
return;
}
var heightExceeded = height && imageInfo.height > height;
if (width && imageInfo.width > width) {
if (heightExceeded) {
throw new Error('maxDimensions');
} else {
throw new Error('maxWidth');
}
}
if (heightExceeded) {
throw new Error('maxHeight');
}
};
}
$(function() {
$('[role=uploadcare-uploader]').each(function() {
var input = $(this);
if ( ! input.data('maxWidth') && ! input.data('maxHeight')) {
return;
}
var widget = uploadcare.Widget(input);
widget.validators.push(maxDimensions(input.data('maxWidth'),
input.data('maxHeight')));
});
});
UPLOADCARE_LOCALE_TRANSLATIONS = {
// messages for widget
errors: {
'maxDimensions': 'This image exceeds max dimensions.',
'maxWidth': 'This image exceeds max width.',
'maxHeight': 'This image exceeds max height.'
},
// messages for dialog’s error page
dialog: { tabs: { preview: { error: {
'maxDimensions': {
title: 'Title.',
text: 'Text.',
back: 'Back'
},
'maxWidth': {
title: 'Title.',
text: 'Text.',
back: 'Back'
},
'maxHeight': {
title: 'Title.',
text: 'Text.',
back: 'Back'
}
} } } }
};
<p>
<code>data-max-width="1024" data-max-height="1024"</code><br>
<input type="hidden" role="uploadcare-uploader" data-max-width="1024" data-max-height="1024">
</p>
<p>
<code>data-images-only="true" data-max-width="1024" data-max-height="1024"</code><br>
<input type="hidden" role="uploadcare-uploader" data-images-only="true" data-max-width="1024" data-max-height="1024">
</p>
data-max-width="1024" data-max-height="1024"
data-images-only="true" data-max-width="1024" data-max-height="1024"
Image Orientation
This validator denies landscape images with the data-portrait-only="true"
attribute and portrait images with the data-landscape-only="true"
attribute. There is no point in adding both of those attributes to the same widget.
function imageOrientation(portrait) {
return function(fileInfo) {
var imageInfo = fileInfo.originalImageInfo;
if (imageInfo === null || imageInfo.width == imageInfo.height) {
return;
}
if (imageInfo.width < imageInfo.height != portrait) {
throw new Error(portrait ? 'landscape' : 'portrait');
}
}
}
$(function() {
$('[role=uploadcare-uploader]').each(function() {
var input = $(this);
if ( ! input.data('portraitOnly') && ! input.data('landscapeOnly')) {
return;
}
var widget = uploadcare.Widget(input);
widget.validators.push(imageOrientation(!! input.data('portraitOnly')));
});
});
UPLOADCARE_LOCALE_TRANSLATIONS = {
// messages for widget
errors: {
'portrait': 'This image exceeds max dimensions.',
'landscape': 'This image exceeds max width.'
},
// messages for dialog’s error page
dialog: { tabs: { preview: { error: {
'portrait': {
title: 'Title.',
text: 'Text.',
back: 'Back'
},
'landscape': {
title: 'Title.',
text: 'Text.',
back: 'Back'
}
} } } }
};
<p>
<code>data-portrait-only="true"</code><br>
<input type="hidden" role="uploadcare-uploader" data-portrait-only="true">
</p>
<p>
<code>data-landscape-only="true"</code><br>
<input type="hidden" role="uploadcare-uploader" data-landscape-only="true">
</p>
data-portrait-only="true"
data-landscape-only="true"