Croppie : How to get output image in JPEG instead of default PNG? - croppie

I use croppie to upload images in my laravel application. The upload part works flawlessly. However, since the PNG image takes more space than the original images. I want to have jpeg images stored on the server instead of PNG and with my own quality parameters provided.
Here is the javascript code I use for uploading images using croppie.
but save image with PNG format
$(function() {
var croppie = null;
var el = document.getElementById('resizer');
$.base64ImageToBlob = function(str) {
// extract content type and base64 payload from original string
var pos = str.indexOf(';base64,');
var type = str.substring(5, pos);
var b64 = str.substr(pos + 8);
// decode base64
var imageContent = atob(b64);
// create an ArrayBuffer and a view (as unsigned 8-bit)
var buffer = new ArrayBuffer(imageContent.length);
var view = new Uint8Array(buffer);
// fill the view, using the decoded base64
for (var n = 0; n < imageContent.length; n++) {
view[n] = imageContent.charCodeAt(n);
}
// convert ArrayBuffer to Blob
var blob = new Blob([buffer], { type: type });
return blob;
}
$.getImage = function(input, croppie) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
croppie.bind({
url: e.target.result,
});
}
reader.readAsDataURL(input.files[0]);
}
}
$("#file-upload").on("change", function(event) {
$("#myModal").modal();
// Initailize croppie instance and assign it to global variable
croppie = new Croppie(el, {
viewport: {
width: 200,
height: 200,
type: 'circle'
},
boundary: {
width: 250,
height: 250
},
enableOrientation: true
});
$.getImage(event.target, croppie);
});
$("#upload").on("click", function() {
croppie.result('base64','original','jpeg',0).then(function(base64) {
$("#myModal").modal("hide");
$("#profile-pic").attr("src","/images/ajax-loader.gif");
var url = "{{ url('/demos/jquery-image-upload') }}";
var formData = new FormData();
formData.append("profile_picture", $.base64ImageToBlob(base64));
// This step is only needed if you are using Laravel
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
type: 'POST',
url: url,
data: formData,
processData: false,
contentType: false,
success: function(data) {
if (data == "uploaded") {
$("#profile-pic").attr("src", base64);
} else {
$("#profile-pic").attr("src","/images/icon-cam.png");
console.log(data['profile_picture']);
}
},
error: function(error) {
console.log(error);
$("#profile-pic").attr("src","/images/icon-cam.png");
}
});
});
});
// To Rotate Image Left or Right
$(".rotate").on("click", function() {
croppie.rotate(parseInt($(this).data('deg')));
});
$('#myModal').on('hidden.bs.modal', function (e) {
// This function will call immediately after model close
// To ensure that old croppie instance is destroyed on every model close
setTimeout(function() { croppie.destroy(); }, 100);
})
});

I faced similar issues a while ago.
I am using the jQuery way as per the docs. The OP is also using jQuery elsewhere, so...
Croppie is attached this way:
upload = $('#upload_div').croppie(method, args);
Instead of passing the parameters like this:
croppie.result('base64','original','jpeg',0).then(function(base64){...
You pass named parameters:
upload.croppie(
'result',
{type: 'base64',
size: 'original',
format: 'jpeg',
quality: 0
}).then(function(base64){ ...

Use:
croppie.result({
type: 'base64',
format: 'jpeg',
viewport:'original',
quality:1,
circle: false
}).then(function (base64) {
...

Related

JQuery-File-Upload using Signed_URL Google Storage, how to call super class function data.submit() within ajax callback?

I have a fileupload HTML element in my DOM and it currently gets multiple files and calls "add" function for each file. For each file, a signed url is received from an ajax call to the related api. After the succesful ajax call to api, I want to call the data.submit() method of the parent function which is the function in fileupload method as first argument.
How may I be able to access that just after "xhr.setRequestHeader('Content-Type', file.type);" ?
The primary inspiration is from this link :http://kevindhawkins.com/blog/django-javascript-uploading-to-google-cloud-storage/
$("#fileupload").fileupload({
dataType: 'json',
sequentialUploads: true,
add: function(e, data) {
$.each(data.files, function(index, file) {
// pack our data to get signature url
var formData = new FormData();
formData.append('filename', file.name);
formData.append('type', file.type);
formData.append('size', file.size);
// Step 3: get our signature URL
$.ajax({
url: '/api/getsignedurl/',
type: 'POST',
processData: false,
contentType: false,
dataType: 'json',
headers: {
'X-CSRFToken': Cookies.get('csrftoken'),
},
context: 'hello',
data: formData,
}).done(function (data) {
// Step 5: got our url, push to GCS
const xhr = new XMLHttpRequest();
if ('withCredentials' in xhr) {
xhr.open("PUT", data.signed_url, true);
}
else if (typeof XDomainRequest !== 'undefined') {
xhr = new XDomainRequest();
xhr.open("PUT", data.signed_url);
}
else {
xhr = null;
}
xhr.onload = () => {
const status = xhr.status;
if (status === 200) {
//alert("File is uploaded");
} else {
}
};
xhr.onerror = () => {
};
xhr.setRequestHeader('Content-Type', file.type);
//data.submit();
});
});
},
If the $this = $(this) is defined prior to the $.each loop :
submit: function(e, data) {
var $this = $(this);
$.each(data.files, function(index, file) { ...
Then the following can be used to access the data in the parent function
this.primary_data.headers={'Content-Type': file.type};
this.primary_data.jqXHR = $this.fileupload('send', this.primary_data);

jsZip - execute generateAsync after Ajax post success

I have number if files to be added in the zip file. some are optional (user choice). I like to execute the generateAsync once all required files Ajax post is successful.
I tried to place a check but its not working.
SAMPLE CODES:
var requestCSS;
var StyleFileData;
var requestAnimatedJS;
var AnimatedScriptData;
function getAllFiles(complileComplete){
requestCSS = $.ajax({
url: 'css/styles.css',
type: "GET",
contentType: "text/css",
mimeType:'text/plain; charset=x-user-defined',
success: function (data){
StyleFileData = data;
}
});
if(animatedBG){
requestAnimatedJS = $.ajax({
url: 'js/animated.js',
type: "GET",
contentType: "text/javascript",
mimeType:'text/plain; charset=x-user-defined',
//async: false,
success: function (data){
AnimatedScriptData = data;
}
});
} else {
requestAnimatedJS = '';
}
}
$('#saveProject').on('click', function(){
getAllFiles(complileComplete);
if(complileComplete === true) {
var zip = new JSZip();
var jsFiles;
var cssFiles;
zip.file("index.html", fullHTML);
jsFiles = zip.folder("js");
cssFiles = zip.folder("css");
requestCSS.done( function( data ) {
cssFiles.file("styles.css", data, { binary: true });
});
if(animatedBG){
requestAnimatedJS.done( function( data ) {
jsFiles.file("particles.js", data, { binary: true });
});
}
zip.generateAsync({type:"blob"})
.then(function(content) {
saveAs(content, "Sample.zip");
});
}
});
No server side or node.js is involved.

SharePoint 2013 - Attach file to custom list using drag and drop

In Sharepoint 2013, is it possible to drag and drop a file (.jpg , .pdf, .png) to a custom list as an attachment? If so, can this be achieved by using a script (JS, jquery)? So, if a user is reporting a bug (NewForm.aspx), and he has a screenshot of the error message saved as a .jpg, I would want him to be able to drop this file into a drop zone on the form.
Can this scenario work - I would be very grateful for your suggestions?
Here is my tested code.
<style type="text/css">
.droppable {
background: #08c;
color: #fff;
padding: 100px 0;
text-align: center;
}
.droppable.dragover {
background: #00CC71;
}
</style>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script type="text/javascript">
function makeDroppable(element, callback) {
var input = document.createElement('input');
input.setAttribute('type', 'file');
input.setAttribute('id', 'dragdropContent');
input.setAttribute('multiple', true);
input.style.display = 'none';
input.addEventListener('change', triggerCallback);
element.appendChild(input);
element.addEventListener('dragover', function (e) {
e.preventDefault();
e.stopPropagation();
element.classList.add('dragover');
});
element.addEventListener('dragleave', function (e) {
e.preventDefault();
e.stopPropagation();
element.classList.remove('dragover');
});
element.addEventListener('drop', function (e) {
e.preventDefault();
e.stopPropagation();
element.classList.remove('dragover');
triggerCallback(e);
});
element.addEventListener('click', function () {
input.value = null;
input.click();
});
function triggerCallback(e) {
var files;
if (e.dataTransfer) {
files = e.dataTransfer.files;
} else if (e.target) {
files = e.target.files;
}
callback.call(null, files);
}
}
$(function () {
String.prototype.format = function () {
var args = [].slice.call(arguments);
return this.replace(/(\{\d+\})/g, function (a) {
return args[+(a.substr(1, a.length - 2)) || 0];
});
};
var element = document.querySelector('.droppable');
function callback(files) {
// Here, we simply log the Array of files to the console.
//console.log(files);
var fileName = files[0].name;
// Construct the endpoint. mydoc is document library name
var reader = new FileReader();
reader.file = files[0];
reader.onload = function (event) {
var arrayBuffer = event.target.result;
//var fileData = '';
//var byteArray = new Uint8Array(arrayBuffer);
//for (var i = 0; i < byteArray.byteLength; i++) {
// fileData += String.fromCharCode(byteArray[i]);
//}
var fileEndpoint = String.format(
"{0}/_api/web/lists/getByTitle('{1}')/RootFolder/files" +
"/add(overwrite=true, url='{2}')",
_spPageContextInfo.webAbsoluteUrl, 'mydoc', fileName);
//Add the file to the SharePoint folder.
$.ajax({
url: fileEndpoint,
type: "POST",
data: arrayBuffer,//fileData,
processData: false,
headers: {
"X-RequestDigest": jQuery("#__REQUESTDIGEST").val(),
"accept": "application/json;odata=verbose",
"content-length": arrayBuffer.byteLength,
//"IF-MATCH": itemMetadata.etag,
//"X-HTTP-Method": "MERGE"
},
success: function (data, b, c) {
alert('File upload succeeded.');
},
error: function (a, b, err) {
alert('Error: ' + err.responseText);
}
})
};
reader.onerror = function (e) {
alert(e.target.error);
}
var arrayBuffer = reader.readAsArrayBuffer(files[0]);
}
makeDroppable(element, callback);
})
</script>
<div class="droppable">
<p>Drag files here or click to upload</p>
</div>
Update:
This is the control in my test sample:
You could try to debug is any JS error in your page.

AWS Lambda Get Image and Upload to S3

I am working in a AWS Lambda function. I am successfully making an API call to the NASA APOD and getting back the values. I want to take the url for the image and download that image and then upload into S3. I am getting an error when I try to access the "test.jpg" image, "Error: EACCES: permission denied, open 'test.jpg'". If I move the S3bucket.putObject outside the http.request, I get data is equal to null. I know I am missing something simple. Thought?
function GetAPOD(intent, session, callback) {
var nasa_api_key = 'demo-key'
, nasa_api_path = '/planetary/apod?api_key=' + nasa_api_key;
var options = {
host: 'api.nasa.gov',
port: 443,
path: nasa_api_path,
method: 'GET'
};
var req = https.request(options, function (res) {
res.setEncoding('utf-8');
var responseString = '';
res.on('data', function (data) {
responseString += data;
});
res.on('end', function () {
console.log('API Response: ' + responseString);
var responseObject = JSON.parse(responseString)
, image_date = responseObject['date']
, image_title = responseObject['title']
, image_url = responseObject['url']
, image_hdurl = responseObject['hdurl']
, image_desc = responseObject['explanation'];
var s3Bucket = new AWS.S3( { params: {Bucket: 'nasa-apod'} } );
var fs = require('fs');
var file = fs.createWriteStream("test.jpg");
var request = http.get(image_url, function(response) {
response.pipe(file);
var data = {Key: "test.jpg", Body: file};
s3Bucket.putObject(data, function(err, data) {
if (err) {
console.log('Error uploading data: ', data);
}
else {
console.log('succesfully uploaded the image!');
}
});
});
});
});
req.on('error', function (e) {
console.error('HTTP error: ' + e.message);
});
//req.write();
req.end();
}
You need to be writing the file to /tmp. That's the only directory in the Lambda environment that you will have write access to.
I got it!! Thank you Mark B for the help. I was able to get the data from the stream without saving it locally and then writing to the bucket. I did have to change my IAM role to allow the putObject for S3.
function GetAPOD(intent, session, callback) {
var nasa_api_key = 'demo-key'
, nasa_api_path = '/planetary/apod?api_key=' + nasa_api_key;
var options = {
host: 'api.nasa.gov',
port: 443,
path: nasa_api_path,
method: 'GET'
};
var req = https.request(options, function (res) {
res.setEncoding('utf-8');
var responseString = '';
res.on('data', function (data) {
responseString += data;
});
res.on('end', function () {
// console.log('API Response: ' + responseString);
var responseObject = JSON.parse(responseString)
, image_date = responseObject['date']
, image_title = responseObject['title']
, image_url = responseObject['url']
, image_hdurl = responseObject['hdurl']
, image_desc = responseObject['explanation'];
var image_name = image_date + '.jpg';
var s3 = new AWS.S3();
var s3Bucket = new AWS.S3( { params: {Bucket: 'nasa-apod'} } );
var request = http.get(image_url, function(response) {
var image_stream = null;
response.on('data', function (data) {
image_stream = data;
});
response.on('end', function () {
var param_data = {Key: image_name, Body: image_stream, ContentType: "image/jpeg", ContentLength: response.headers['content-length']};
s3Bucket.putObject(param_data, function(err, output_data) {
if (err) {
console.log('Error uploading data to S3: ' + err);
}
});
});
});
request.end();
});
});
req.on('error', function (e) {
console.error('HTTP error: ' + e.message);
});
req.end();
}

google maps marker load via ajax and infocontent

In my app I have a google map and I want to add many marker on it and so I load the data via ajax (I'm in Django). I have the probem with infocontent and the 'click' event on the marker load via ajax: When I do 'click' on the marker nothing happened. This is my code:
function initialize() {
var latlng = new google.maps.LatLng({{lat}}, {{long}});
var myOptions = {
zoom: 16,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("mapCanvas"), myOptions);
var contentString = '<div id="content">{{name}}<br><span style="font-size:10px;">{{road}}</span><br><span style="font-size:10px;">{{city}} ({{prov}})</span></div>';
var infowindow_strutt = new google.maps.InfoWindow({
content: contentString
});
var marker = new google.maps.Marker({
position: latlng,
map: map,
title: '{{name}}'
});
google.maps.event.addListener(marker, 'click', function() {
infowindow_strutt.open(map,marker);
});
var markers = [];
var markers_strutt = [];
var markers_concor = [];
var icon_strutt = {
url: 'http://icons.iconarchive.com/icons/graphicloads/colorful-long-shadow/24/Home-icon.png'
};
var icon_concor = {
url: 'http://icons.iconarchive.com/icons/graphicloads/100-flat/24/home-icon.png'
};
var marker_concor
var marker_strutt
map.addListener('bounds_changed', function() {
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(null);
}
var bounds = map.getBounds();
var southWest = bounds.getSouthWest();
var northEast = bounds.getNorthEast();
$.ajax({
url: '/api/get_marker/',
cache: false,
data: {
'fromlat': southWest.lat(),
'tolat': northEast.lat(),
'fromlng': southWest.lng(),
'tolng': northEast.lng()
},
dataType: 'json',
type: 'GET',
async: false,
success: function (data) {
if (data) {
$.each(data, function (i, item) {
if (item.type = 1) {
var marker_concor = new google.maps.Marker({
position: new google.maps.LatLng(item.lat, item.lng),
icon: icon_concor,
map: map,
draggable: false
});
} else if (item.type = 2) {
var marker_strutt = new google.maps.Marker({
position: new google.maps.LatLng(item.lat, item.lng),
icon: icon_strutt,
map: map,
draggable: false
});
//Create an infoWindow
var infowindow_strutt = new google.maps.InfoWindow();
//set the content of infoWindow (the name)
infowindow_strutt.setContent(item.name);
//add click listner to marker which will open infoWindow
map.addListener(marker_strutt, 'click', function() {
infowindow_strutt.open(marker_strutt); // click on marker opens info window
});
}
markers_concor.push(marker_concor);
markers_strutt.push(marker_strutt);
if (marker_strutt) {
marker_strutt.setMap(map);
}
if (marker_concor) {
marker_concor.setMap(map);
}
});
}
}
});
});
}
jQuery(document).ready(function(e) {
initialize();
});
Where is the issue? Thanks a lot
EDIT: View code
def view_get_marker(request):
id = 24
list_id = []
list_marker = []
list_id.append(id)
# type 1 data
A_list = tab_A.objects.filter(id_struttura=id).filter(lat__gt=request.GET.get('fromlat'), lat__lt=request.GET.get('tolat')).filter(lng__gt=request.GET.get('fromlng'), lng__lt=request.GET.get('tolng'))
for a in A_list:
list_marker.append([a.lat, a.lng, a.name, a.road, a.city, a.id, 1])
list_id.append(a.id)
# type 2 data
B_list = list(tab_B.objects.all().values_list('lat','lng','name','road','city','id').exclude(lng__isnull=True).exclude(id__in=lista_id).filter(lat__gt=request.GET.get('fromlat'), lat__lt=request.GET.get('tolat')).filter(lng__gt=request.GET.get('fromlng'), lng__lt=request.GET.get('tolng')))
for lat, lng, name, road, city, id in B_list:
list_marker.append([lat, lng, name, road, city, id, 2])
if request.is_ajax():
results = []
for row in list_marker:
h_json = {}
h_json['lat'] = row[0]
h_json['lng'] = row[1]
h_json['name'] = unicode(row[2])
h_json['road'] = unicode(row[3])
h_json['city'] = unicode(row[4])
h_json['id'] = row[5]
h_json['type'] = row[6]
results.append(h_json)
data = json.dumps(results)
else:
data = 'fail'
mimetype = 'application/json'
return HttpResponse(data, mimetype)
EDIT 2:
I found the solution. The problem was in the event 'click' declaration. The right way is this:
google.maps.event.addListener(marker_strutt, 'click', (function(marker_strutt, i) {
return function() {
infowindow.setContent('my content');
infowindow.open(map, marker_strutt);
}
})(marker_strutt, i));
In this way I have the popoup!