Stop file upload when filesize too large - jQuery S3 - javascript

Please view the snippet below. I am using jQuery fileUpload and a direct s3 form to upload videos to AWS. I would like there to be a filesize limit of 5mb which is imposed before the video hits any local server. How can I amend this code so that the upload is halted completely and alerts the user when the filesize is over 5mb and if its under, everything carries on as usual?
I have added a content length limit of 5mb to the S3 form options, so uploads of larger than this are refused, but it would be preferable if there was something to notify the user that an upload is too large to start with.
$ ->
$(".direct-upload").each ->
form = $(this)
$(this).fileupload
url: form.attr("action")
type: "POST"
autoUpload: true
dataType: "xml"
add: (event, data) ->
if data.files[0].size < 5242880
$.ajax
url: "/signed_urls"
type: "GET"
dataType: "json"
data:
doc:
title: data.files[0].name
async: false
success: (data) ->
form.find("input[name=key]").val data.key
form.find("input[name=policy]").val data.policy
form.find("input[name=signature]").val data.signature
data.submit()
send: (e, data) ->
$(".progress, #dropzone").fadeIn()
$.each data.files, (index, file) ->
$('.well').html("").append("Uploading: " + file.name + '<br>' + "File size: " + (file.size / 1000000 ) + ' MB')
progress: (e, data) ->
percent = undefined
percent = Math.round((e.loaded / e.total) * 100)
$(".bar").css "width", percent + "%"
fail: (e, data) ->
console.log "fail"
success: (data) ->
url = undefined
url = decodeURIComponent($(data).find("Location").text())
$("#video_file").val url
done: (event, data) ->
$("#new_video").submit()
$(".progress").fadeOut 1200, ->
$(".bar").css "width", 0
UPDATE:
This works nicely. Moving the if statement before the /signed_url prevents a file that is too big being sent to the server and alerts the user.
$ ->
$(".direct-upload").each (data) ->
form = $(this)
$(this).fileupload
url: form.attr("action")
type: "POST"
autoUpload: true
dataType: "xml"
add: (event, data) ->
if data.files[0].size < 5242880
$.ajax
url: "/signed_urls"
type: "GET"
dataType: "json"
data:
doc:
title: data.files[0].name
async: false
success: (data) ->
form.find("input[name=key]").val data.key
form.find("input[name=policy]").val data.policy
form.find("input[name=signature]").val data.signature
data.submit()
else
alert("File too big")
send: (e, data) ->
$(".progress, #dropzone").fadeIn()
$.each data.files, (index, file) ->
$('.well').html("").append("Uploading: " + file.name + '<br>' + "File size: " + (Math.round(file.size / 1000000 )) + ' MB')
progress: (e, data) ->
percent = undefined
percent = Math.round((e.loaded / e.total) * 100)
$(".bar").css "width", percent + "%"
fail: (e, data) ->
console.log "fail"
success: (data) ->
url = undefined
url = decodeURIComponent($(data).find("Location").text())
$("#video_file").val url
done: (event, data) ->
$("#new_video").submit()
$(".progress").fadeOut 1200, ->
$(".bar").css "width", 0

<form method="post" action="./step2.php" enctype="multipart/form-data" id="formID" name="formID">
<input type="text" name="title" id="title" />
<input type="file" name="pptfile" id="pptfile"/>
<input type="submit" name="btn" id="btn" />
<script type="text/javascript">
function checkUpload(size)
{
if(size>25)
{
var n = size.toFixed(2);
alert('Your file size is: ' + n + "MB, and it is too large to upload! Please try to upload smaller file (25MB or less).");
document.getElementById("btn").style.display='none';
}
else
{
//alert('File size is OK');
$('#tbn').show();
}
}
$('#pptfile').bind('change', function() {
var fileSize = this.files[0].size/1024/1024;
checkUpload(fileSize);
});
</script>
</form>

That's pretty much exactly the same way I do it. If you don't submit it, it won't send the file.
Do you want to be submitting that ajax requested to /signed_urls when the filesize is too big? Maybe you should move all of that inside the if data.files[0].size < 5242880 block?

Working for me:
checkFileSize(event) {
f = document.getElementById('id_ifile');
if (f.files.length > 0 && f.files[0].size > 3 * 1024 ** 2) {
alert( 'The file is too large (no more than 3MB)' );
event.preventDefault();
}
}

Related

Plupload Overall Progress issue

I have below code in before upload event for a Plupload control in my aspx page which has three upload control for upload images. my problem is when "Validate_Img_File_Name.ashx" returns not success output and stop the specific file upload the overall progress bar and the progress percentage is not finishing at 100%. function "_updateTotalProgress:" in jquery.ui.plupload.js do the overall progress I guess, but I have no idea of how to overcome this issues since my knowledge of java is zero. how can I get the correct overall progress ? your help is highly appreciated.
BeforeUpload: function (up, file) {
// Called right before the upload for a given file starts, can be used to cancel it if required
//log('[BeforeUpload]', 'File: ', file);
$.ajax({
url: "../Validate_Img_File_Name.ashx",
type: "POST",
datatype: 'text',
data: { filename: file.name },
cache: false,
}).done(function (data) {
if (data == "SUCCESS") {
up.settings.url = '/bulk_img_uploader.ashx';
file.status = plupload.UPLOADING;
up.trigger("UploadFile", file);
up.settings.url = '';
log('File:', file, '- OK');
} else {
//alert(file.name + " " + "fail");
up.stop();
file.status = plupload.FAILED;
up.trigger('QueueChanged'); //Line A
up.trigger('UploadProgress', file); // Line B
up.start();
log('File:', file, ' - ' + data);
return false;
}
});
},

File Upload send to different urls depending on type

I'm using Jquery File Upload and I have some coffeescript that looks like:
$('.fileupload').fileupload
dataType: "json"
add: (e, data) ->
file = data.files[0]
types = /(\.|\/)(gif|jpe?g|png)$/i
if (types.test(file.type) || types.test(file.name))
data.submit()
else
alert("Oops, " + file.name + " is not a supported filetype")
progress: (e, data) ->
done: (e, data) ->
Basically, what I want to do is send to different urls based on what type of file is uploaded. For example, if a pdf is uploaded I'd like to send it to www.website.com/process/pdf whereas if it's a png/gif/jpeg send it to www.website.com/process/image.
Is this possible client side with jQuery File Upload?
You can change the data object
$('.fileupload').fileupload
dataType: "json"
add: (e, data) ->
file = data.files[0]
types = /(\.|\/)(gif|jpe?g|png)$/i
pdf = /(\.|\/)(pdf)$/i
if (types.test(file.type) || types.test(file.name))
data.url = 'www.website.com/process/image'
data.submit()
else if (pdf.test(file.type) || pdf.test(file.name))
data.url = 'www.website.com/process/pdf'
data.submit()
else
alert("Oops, " + file.name + " is not a supported filetype")
progress: (e, data) ->
done: (e, data) ->
jQuery File Upload: how to change the upload url dynamically

jQuery File Upload in Rails 4.x Nested Form

I have a Horse model and a Photo model. I am using jQuery File Upload to resize (client side) images and save on Amazon s3 directly since I am using Heroku.
I have seen other questions similar that use carrierwave, paperclip, or that are very old. I am not sure why you would use carrierwave/paperclip, but I think based on what heroku says, I do not want to have images hitting the server potentially causing time-outs.
Heroku recommends using jQuery File Upload and shows js appending new file input with a value of the image's link (returned from amazon s3). I have this working when saving a photo separately. I now want to make it work in a nested form for Horse but js is not finding input (since it does not exist yet because it's nested I presume).
I am using Cocoon for nested forms (I am open to anything that will work better). I am not too familiar with javascript/jQuery but a far as I can tell, Cocoon 'hides' the nested element until I click to add it via the add_association.
haml view code:
= link_to_add_association 'add photo', f, :photos
html source before clicking 'add photo'
<div class='links'>
<a class="btn btn-default btn-sm add_fields" data-association-insertion-method="after" data-association="photo" data-associations="photos" data-association-insertion-template="<div class='nested-fields'>
<fieldset class="inputs"><ol><input type="file" name="horse[photos_attributes][new_photos][url]" id="horse_photos_attributes_new_photos_url" />
<input type="hidden" name="horse[photos_attributes][new_photos][_destroy]" id="horse_photos_attributes_new_photos__destroy" value="false" /><a class="remove_fields dynamic" href="#">remove photo</a>
</ol></fieldset>
</div>
" href="#">add photo</a>
How do I work with this input and how do I handle multiple file uploads as they are added correctly?
My current upload js:
$(function() {
if ($('#new_horse').length > 0) {
$.get( "/presign", function( s3params ) {
$('.direct-upload').find("input:file").each(function(i, elem) {
var fileInput = $(elem);
var form = $(fileInput.parents('form:first'));
var submitButton = form.find('input[type="submit"]');
var progressBar = $("<div class='bar'></div>");
var barContainer = $("<div class='progress'></div>").append(progressBar);
fileInput.fileupload({
fileInput: fileInput,
url: "http://" + s3params.url.host,
type: 'POST',
autoUpload: true,
formData: s3params.fields,
paramName: 'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
dataType: 'XML', // S3 returns XML if success_action_status is set to 201
disableImageResize: false,
imageQuality: 0.5,
disableImageResize: /Android(?!.*Chrome)|Opera/
.test(window.navigator && navigator.userAgent),
imageMaxWidth: 500,
imageMaxHeight: 1000,
imageOrientation: true, //auto rotates images
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i, //I added this to jquery.fileupload-validate: alert('Must Be JPG GIF or PNG Image')
replaceFileInput: false,
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
progressBar.css('width', progress + '%')
},
start: function (e) {
submitButton.prop('disabled', true);
fileInput.after(barContainer);
progressBar.
css('background', 'green').
css('display', 'block').
css('width', '0%').
text("Loading...");
},
done: function(e, data) {
submitButton.prop('disabled', false);
progressBar.text("Pre-uploading done... Please Save or Cancel");
// extract key and generate URL from response
var key = $(data.jqXHR.responseXML).find("Key").text();
var url = 'https://' + s3params.url.host +'/' + key;
// remove first input to prevent phantom upload delay
fileInput.remove();
// create new hidden input with image url
var input = $("<input />", { type:'hidden', name: fileInput.attr('name'), value: url })
var imgPreview = '<img src="' + url + '">';
form.append(input);
form.append(imgPreview);
},
fail: function(e, data) {
submitButton.prop('disabled', false);
progressBar.
css("background", "red").
text("Failed");
}
});
});
}, 'json');
}
});
I guess I should have looked at cocoon documentation first:
http://www.rubydoc.info/gems/cocoon#Callbacks__upon_insert_and_remove_of_items_
http://www.rubydoc.info/gems/cocoon/1.2.6
I modified my upload.js file to the following and it worked for multiple files in nested forms perfectly:
// added for file uploading
// https://devcenter.heroku.com/articles/direct-to-s3-image-uploads-in-rails
// Get our s3params from our endpoint
$(document).on('ready page:load', function () {
$('.direct-upload')
.on('cocoon:after-insert', function(e, photo) {
console.log('inside cocoon image function');
$.get( "/presign", function( s3params ) {
$('.direct-upload').find("input:file").each(function(i, elem) {
console.log('inside nested-fields photo input form');
var fileInput = $(elem);
var form = $(fileInput.parents('form:first'));
var submitButton = form.find('input[type="submit"]');
var progressBar = $("<div class='bar'></div>");
var barContainer = $("<div class='progress'></div>").append(progressBar);
fileInput.fileupload({
fileInput: fileInput,
url: "http://" + s3params.url.host,
type: 'POST',
autoUpload: true,
formData: s3params.fields,
paramName: 'file', // S3 does not like nested name fields i.e. name="user[avatar_url]"
dataType: 'XML', // S3 returns XML if success_action_status is set to 201
disableImageResize: false,
imageQuality: 0.5,
disableImageResize: /Android(?!.*Chrome)|Opera/
.test(window.navigator && navigator.userAgent),
imageMaxWidth: 500,
imageMaxHeight: 1000,
imageOrientation: true, //auto rotates images
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i, //I added this to jquery.fileupload-validate: alert('Must Be JPG GIF or PNG Image')
replaceFileInput: false,
previewMaxWidth: 100,
previewMaxHeight: 100,
previewCrop: true,
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
progressBar.css('width', progress + '%')
},
start: function (e) {
submitButton.prop('disabled', true);
fileInput.after(barContainer);
progressBar.
css('background', 'green').
css('display', 'block').
css('width', '0%').
text("Loading...");
},
done: function(e, data) {
submitButton.prop('disabled', false);
progressBar.text("Photo Uploaded");
// extract key and generate URL from response
var key = $(data.jqXHR.responseXML).find("Key").text();
var url = 'https://' + s3params.url.host +'/' + key;
// remove first input to prevent phantom upload delay
fileInput.remove();
// create new hidden input with image url
var input = $("<input />", { type:'hidden', name: fileInput.attr('name'), value: url })
var imgPreview = '<img src="' + url + '">';
form.append(input);
form.append(imgPreview);
},
fail: function(e, data) {
submitButton.prop('disabled', false);
progressBar.
css("background", "red").
text("Failed");
}
}, 'json'); //fileupload
}); //each file
}); //presign call
}); // function cocoon
}); // page ready
I guess Google and a well documented gem can replace knowledge of JS in the short term :-) I am sure it's not at tight as it could be so please offer any improvements.

jQuery-File-Upload- show selected file physical path

i am using this plug in for file upload
my problem is , when i click on
<input type="file" class="upload" id="imgAuthorImageUpload" accept="image/gif, image/jpeg,image/jpg,image/bmp,image/pjpeg,image/png" />
imgAuthorImageUpload - the popup will open from explore and it will let you chose the file for upload
as soon as it start to upload, i want to show that file location on page,
for example,
if i chose animal.png from d drive picture folder: then i want to display something like this
D:/Pictures/animal.png
the code i wrote like this :
$("#imgAuthorImageUpload").fileupload({
url: '/picture/DashBoard/pictureUpload.ashx',
dataType: 'json',
cache: false,
async: true,
}).on('fileuploadadd', function (e, data) {
e.preventDefault();
}).on('fileuploaddone', function (e, data) {
alert("upload done");
e.preventDefault();
}).on('fileuploadprogress', function (e, data) {
var percentVal = '0%';
var percentVal = parseInt(data.loaded / data.total * 100, 10);
$('.bar').css(
'width',
percentVal + '%'
);
$('.percent').html(percentVal + '%');
}).on('fileuploadcomplete', function (e, data) {
alert("Upload complete");
});
For security reasons, browsers don't allow this.
A good explanation is provided here: Full path from file input using jQuery

Why the text before Ajax call is not display?

function pdfToImgExec(file, IsfirstLogging, folder, round) {
alert(file);
var postString = file + '&' + IsfirstLogging + '&' + folder + '&' + round;
var errorMsg = (folder == 'Incoming' ? '<p>error in incoming folder</p>' : '<p>error in other folder</p>');
$.ajax({
type: "POST",
cache: false,
async: false,
url: "pdfToImgExec.php",
data: {
"data": postString
},
dataType: "html",
beforeSend: function () {
alert(file + 'a');
$('#pdfToImgResult').html('<p>Converting' + file + ', Please wait......</p>');
},
success: function (data) {
if(data == '1') {
$('#pdfToImgResult').html('<p>Complete convert ' + file + '</p>');
} else if(round < 4) {
$('#pdfToImgResult').html('<p>Fail to convert , retry ' + round + ' round <img src="loading.gif" height="20" width="20"/></p>');
round++;
pdfToImgExec(file, 'false', folder, round);
} else {
folder == 'Incoming' ? tempFailIncomingFiles.push(file) : tempFailResultFiles.push(file);
}
},
error: function (x, t, m) {
$('#pdfToImgResult').html(errorMsg);
alert(t);
releaseBtn();
}
});
}
The problem of this ajax call is I can alert the (file + 'a') in the beforeSend function , but the
$('#pdfToImgResult').html('<p>Converting' + file + ', Please wait......</p>');
is not working, it will not display anything but only jumped to the
$('#pdfToImgResult').html('<p>Complete convert ' + file + '</p>');
after the ajax call is finished.
Is it due to async:false? How to fix the problem ? thanks.
It's because you're using async: false,, so the function blocks until the request is complete, preventing a redraw until everything is done.
You seem to be all set up with callbacks, so there doesn't seem to be any reason to make a blocking xhr request. Just remove the async: false,, and you should be all set.
Here's a quick example of how to deal with asynchronous code. I've removed most of your code to keep it brief.
// --------------------------------new parameter-------------v
function pdfToImgExec(file, IsfirstLogging, folder, round, callback) {
// your code...
$.ajax({
type: "POST",
cache: false,
// async: false, // Remove this line!
url: "pdfToImgExec.php",
data: {
"data": postString
},
dataType: "html",
beforeSend: function () {
$('#pdfToImgResult').html('<p>Converting' + file + ', Please wait......</p>');
},
success: function (data) {
// your code...
// Invoke the callback, passing it the data if needed
callback(data)
},
error: function (x, t, m) {
// your code;
}
});
}
When you call pdftoImgExec, pass a function as the last parameter that will be invoked when the response is complete. That function is where your code resumes.
pdfToImgExec(..., ..., ..., ..., function(data) {
// resume your code here.
alert(data);
})

Categories

Resources