Parsing a JSON response after a file upload with jquery - javascript

I have written a small script using jquery to upload a file to a server. The file is uploaded successfully and the done: event is called with no problems, but I am having issues to process the answer. This is my script:
<input id="fileupload" type="file" name="carPicture" accept="image/*" multiple>
<div id="progress">
<div class="bar" style="width: 0%;"></div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js" type="text/javascript"></script>
<script src="#routes.Assets.at("javascripts/vendor/jquery.ui.widget.js")" type="text/javascript"></script>
<script src="#routes.Assets.at("javascripts/jquery.iframe-transport.js")" type="text/javascript"></script>
<script src="#routes.Assets.at("javascripts/jquery.fileupload.js")" type="text/javascript"></script>
<script>
$(function () {
'use strict';
// Change this to the location of your server-side upload handler:
var url = "uploadCarPicture";
$('#fileupload').fileupload({
url: url,
dataType: 'json',
done: function (e, data) {
$.each(data.result.files, function (index, file) {
$('<p/>').text(file.name).appendTo('#files');
});
},
fail: function (e, data) {
alert("File exists");
},
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .bar').css(
'width',
progress + '%'
);
}
}).prop('disabled', !$.support.fileInput)
.parent().addClass($.support.fileInput ? undefined : 'disabled');
});
</script>
I am having two problems:
the variable data seems to be empty since the loop below doesn't run even once.
$.each(data.result.files, function (index, file) {
$('<p/>').text(file.name).appendTo('#files');
});
The answer is a JSON document with the following format: {"e":0} where "e" is an error code. "e" could return many different values and I would like to be able to find out the real response and not always assume 0.
Any idea?

I have solved it. I've made a small change in the java script like this:
done: function (e, data) {
$.each(data.files, function (index, file) {
$('<p/>').text(file.name);
});
},
And I have changed the json that the server was responding to this format:
{
files:
[
{
error: 0,
name: "thumb2.jpg",
}
]
}

Related

how to upload multiple images with resizing in jquery to django backend server

I am using Jquery file upload and compressing code for images with this i can select multiple images but it only compressing and uploading the last image selected
so how can i upload multiple images with compression? What modifications are needed plzz suggest.
Html code:
<input id="fileupload" type="file" name="file" multiple>
Jquery code:
function csrfSafeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$(function () {
'use strict';
var csrftoken = $.cookie('csrftoken');
var url = '/dashboard/{{name}}/{{name_product_type.type_product|urlencode}}/{{abc}}/';
$('#postbtn').on('click', function () {
var $this = $(this),
data = $this.data();
$this
.off('click')
.text('Abort')
.on('click', function () {
$this.remove();
data.abort();
});
data.submit().always(function () {
$this.remove();
});
});
$('#fileupload').fileupload({
url: url,
crossDomain: false,
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type)) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
},
dataType: 'json',
uploadMultiple: true, // allow multiple upload
autoProcessQueue: false, // prevent dropzone from uploading automatically
maxFiles: 5,
autoUpload: false,
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
maxFileSize: 5000000, // 5 MB
// Enable image resizing, except for Android and Opera,
// which actually support image resizing, but fail to
// send Blob objects via XHR requests:
disableImageResize: /Android(?!.*Chrome)|Opera/
.test(window.navigator.userAgent),
previewMaxWidth: 100,
previewMaxHeight: 100,
previewCrop: true
}).on('fileuploadadd', function (e, data) {
data.context = $('<div/>').appendTo('#files');
$.each(data.files, function (index, file) {
var node = $('<p/>')
.append($('<span/>').text(file.name));
if (!index) {
node
.append('<br>')
// .append($('#postbtn').clone(true).data(data));
}
node.appendTo(data.context);
});
}).on('fileuploadprocessalways', function (e, data) {
var index = data.index,
file = data.files[index],
node = $(data.context.children()[index]);
if (file.preview) {
node
.prepend('<br>')
.prepend(file.preview);
}
if (file.error) {
node
.append('<br>')
.append(file.error);
}
if (index + 1 === data.files.length) {
data.context.find($('#postbtn').data(data));
// .text('Upload')
// .prop('disabled', !!data.files.error);
}
}).on('fileuploadprogressall', function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .progress-bar').css(
'width',
progress + '%'
);
}).on('fileuploaddone', function (e, data) {
$.each(data.result.files, function (index, file) {
var link = $('<a>')
.attr('target', '_blank')
.prop('href', file.url);
$(data.context.children()[index])
.wrap(link);
});
}).on('fileuploadfail', function (e, data) {
$.each(data.result.files, function (index, file) {
var error = $('<span/>').text(file.error);
$(data.context.children()[index])
.append('<br>')
.append(error);
});
}).prop('disabled', !$.support.fileInput)
.parent().addClass($.support.fileInput ? undefined : 'disabled');
});
Django backend :
in views.py :
files=request.FILES.getlist('file')
and then save it to database.
Everrthing works fine. Even image is compressed at the output but we intent to have multiple images compressed and save back to database at one hit of button.
Any sugestions are welcomed...
Thank you...

jquery file upload basic plus mutiple file upload

I am using basic plus of jquery file upload, and i am trying to have one upload button to upload multiple files at same time but its current showing multiple upload buttons if i select multiple files, you can see try it online at here
HTML Code
<span class="btn btn-success fileinput-button">
<i class="glyphicon glyphicon-plus"></i>
<span>Add files...</span>
<!-- The file input field used as target for the file upload widget -->
<input id="fileupload" type="file" name="files[]" multiple>
</span>
<br>
<br>
<!-- The global progress bar -->
<div id="progress" class="progress">
<div class="progress-bar progress-bar-success"></div>
</div>
<!-- The container for the uploaded files -->
<div id="files" class="files"></div>
JS Code
$(function () {
'use strict';
// Change this to the location of your server-side upload handler:
var url = '',
uploadButton = $('<button/>')
.addClass('btn btn-primary')
.prop('disabled', true)
.text('Processing...')
.on('click', function () {
var $this = $(this),
data = $this.data();
$this
.off('click')
.text('Abort')
.on('click', function () {
$this.remove();
data.abort();
});
data.submit().always(function () {
$this.remove();
});
});
$('#fileupload').fileupload({
url: url,
dataType: 'json',
autoUpload: false,
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
maxFileSize: 5000000, // 5 MB
// Enable image resizing, except for Android and Opera,
// which actually support image resizing, but fail to
// send Blob objects via XHR requests:
disableImageResize: /Android(?!.*Chrome)|Opera/
.test(window.navigator.userAgent),
previewMaxWidth: 100,
previewMaxHeight: 100,
previewCrop: true
}).on('fileuploadadd', function (e, data) {
data.context = $('<div/>').appendTo('#files');
$.each(data.files, function (index, file) {
var node = $('<p/>')
.append($('<span/>').text(file.name));
if (!index) {
node
.append('<br>')
.append(uploadButton.clone(true).data(data));
}
node.appendTo(data.context);
});
}).on('fileuploadprocessalways', function (e, data) {
var index = data.index,
file = data.files[index],
node = $(data.context.children()[index]);
if (file.preview) {
node
.prepend('<br>')
.prepend(file.preview);
}
if (file.error) {
node
.append('<br>')
.append($('<span class="text-danger"/>').text(file.error));
}
if (index + 1 === data.files.length) {
data.context.find('button')
.text('Upload')
.prop('disabled', !!data.files.error);
}
}).on('fileuploadprogressall', function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .progress-bar').css(
'width',
progress + '%'
);
}).on('fileuploaddone', function (e, data) {
$.each(data.result.files, function (index, file) {
if (file.url) {
var link = $('<a>')
.attr('target', '_blank')
.prop('href', file.url);
$(data.context.children()[index])
.wrap(link);
} else if (file.error) {
var error = $('<span class="text-danger"/>').text(file.error);
$(data.context.children()[index])
.append('<br>')
.append(error);
}
});
}).on('fileuploadfail', function (e, data) {
$.each(data.files, function (index) {
var error = $('<span class="text-danger"/>').text('File upload failed.');
$(data.context.children()[index])
.append('<br>')
.append(error);
});
}).prop('disabled', !$.support.fileInput)
.parent().addClass($.support.fileInput ? undefined : 'disabled');
});
Its working but shows multiple upload buttons if i select multiple files to upload but i want to have one upload button which can process all uploaded files at same time. Thanks for your help.

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

jQuery File Upload done function

I've modified the example code provided on jQuery File Upload's Wiki My scripting works for the add callback but not the done callback. The server is getting the post correctly and returning a JSON response.
I've noticed in the source code some of the callbacks are commented out. I'm not sure if I should uncomment them or not. Or use the callback fileuploaddone But removing the comment did not work.
Not sure if i'm doing this correctly. I'd like the server to return me a JSON object describing the image I just uploaded so the next step of my form can link the image with a backbone.js model.
<form id="uploadform">
<input id="fileupload" type="file" name="imagefile" data-url="imagefiles" multiple>
<button type="#" class="btn btn-primary uploadfile" style="display: none">Upload</button>
<div id="progress">
<div class="bar" style="width: 0%;"></div>
</div>
</form>
<script>
$(function () {
$('#fileupload').fileupload({
dataType: 'json',
done: function (e, data) {
data.context = $('.uploadfile').css('display','none')
utils.addValidationSuccess('Added file: ' + data.jqXHR.name);
},
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .bar').css(
'width',
progress + '%'
);
},
add: function (e, data) {
console.log('added');
data.context = $('.uploadfile')
.css('display','block')
.click(function () {
utils.showAlert('Uploading','...', 'alert-warning');
data.submit();
});
}
});
});
</script>
What got things working was using jquery.ajax 's apparently native callback on submit, adjusted code shown below.
<div class="row-fluid">
<form id="uploadform">
<input id="fileupload" type="file" name="imagefile" data-url="imagefiles" multiple>
<button type="#" class="btn btn-primary uploadfile" style="display: none">Upload</button>
<div id="progress">
<div class="bar" style="width: 0%;"></div>
</div>
</form>
<script>
$(function () {
$('#fileupload').fileupload({
dataType: 'json',
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .bar').css(
'width',
progress + '%'
);
},
add: function (e, data) {
console.log('added');
data.context = $('.uploadfile')
.css('display','block')
.click(function () {
utils.showAlert('Uploading','...', 'alert-warning');
var jqXHR = data.submit()
.success(function (result, textStatus, jqXHR) {
console.log('Done');
console.log('e:' + e);
console.log('results:' + result );
console.log('results.id:' + result.id );
console.log('textStatus:' + textStatus );
console.log('jqXHR:' + jqXHR );
data.context = $('.uploadfile').css('display','none')
utils.showAlert('Success','the file uploaded successfully','alert-success');
// utils.addValidationSuccess('Added file: ' + data.jqXHR.name);
})
.error(function (jqXHR, textStatus, errorThrown){
utils.showAlert('Error','...', 'alert-error');
});
});
}
});
});
</script>
</div>
I had the same problem with this code.
$(function () {
$('#fileupload').fileupload({
dataType: 'json',
done: function (e, data) {
alert("done");
}
});
});
Just with not setting the dataType, the done callback is now executed ...
Code below just work ...
$(function () {
$('#fileupload').fileupload({
done: function (e, data) {
alert("done");
}
});
});
The server return some json.

Categories

Resources