django using xhr change image from db(sqlite) - ajax

I want to load two images from sqlite(db) using xhr, and when click one image than the data will be send to server (asynchronous) and two images will be change to next images from db. now i have no errors but i can't see image on browser. i think json - django - db connection is not correct.
i wrote code now only for one image. please teach me
survey.html
<script type="text/javascript">
var xhr = new XMLHttpRequest();
xhr.onload = function () {
{% for wheel in wheels|slice:"1:2" %}
xhr.open('GET', '{{ wheel.wheel_sample.url }}', true);
var img = new Image();
var response = xhr.responseText;
var binary = ""
for(i=0;i<response.length;i++){
binary += String.fromCharCode(response.charCodeAt(i) & 0xff);
}
img.src = 'data:image/jpeg;base64,' + btoa(binary);
var canvas = document.getElementById('showImage');
var context = canvas.getContext('2d');
context.drawImage(img,0,0);
{% endfor %}
}
xhr.overrideMimeType('text/plane; charset=x-user-defined');
xhr.send();
</script>
<div class="wheels-img-container">
<canvas class="wheel-first" id="showImage" onclick="img1_click();" width="135" height="135"/>
<canvas class="wheel-second" id="showImage2" onclick="img2_click();" width="135" height="135"/>
</div>
views.py
def survey(request):
json_serializer = serializers.get_serializer("json")()
wheels = json_serializer.serialize(Wheel.objects.all(), ensure_ascii=False)
return render(request, 'polls/survey.html', {'wheels' : wheels})
models.py
image_storage = FileSystemStorage(
# Physical file location ROOT
location='/media/'.format(settings.MEDIA_ROOT),
# Url for file
base_url='/media/'.format(settings.MEDIA_URL),
)
def image_directory_path(instance, filename):
# file will be uploaded to MEDIA_ROOT/media/<filename>
return 'media/{0}'.format(filename)
def logo_directory_path(instance, filename):
# file will be uploaded to MEDIA_ROOT/dashboard/picture/<filename>
return 'media/{0}'.format(filename)
class Wheel(models.Model):
wheel_sample = models.ImageField(blank=True,
upload_to=image_directory_path, storage=image_storage)
wheel_name = models.CharField(max_length=200, null=True)
votes = models.IntegerField(default=0)

Related

convert .heic image to jpg image format in laravel

I have added intervention/image package to convert image format in laravel.
image converted successfully but after uploading image quality was so bad.
Original Image
Uploaded Image
$img =(string) Image::make($image['base64'])
->resize(500, 500)->encode('jpg',100);;
$img = base64_encode($img);
To convert Heic image you have to use imagick, can you use this instead
This is how to install https://ourcodeworld.com/articles/read/645/how-to-install-imagick-for-php-7-in-ubuntu-16-04
try {
$image = new \Imagick();
$image->readImageBlob($image['base64']));
$image->setImageFormat("jpeg");
$image->setImageCompressionQuality(100);
$image->writeImage($targetdir.$uid.".jpg");
}
catch (\ImagickException $ex) {
/**#var \Exception $ex */
return new JSONResponse(["error" => "Imagick failed to convert the images, check if you fulfill all requirements." , "details" => $ex->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
}
A bit late, but I had the same problem.
I managed to do it with the heic2any js library (https://github.com/alexcorvi/heic2any/blob/master/docs/getting-started.md)
I converted the picture on client side, then gave it to the input in client side.
Server is seeing it as it was originally uploaded as jpg.
function convertHeicToJpg(input)
{
var fileName = $(input).val();
var fileNameExt = fileName.substr(fileName.lastIndexOf('.') + 1);
if(fileNameExt == "heic") {
var blob = $(input)[0].files[0]; //ev.target.files[0];
heic2any({
blob: blob,
toType: "image/jpg",
})
.then(function (resultBlob) {
var url = URL.createObjectURL(resultBlob);
$(input).parent().find(".upload-file").css("background-image", "url("+url+")"); //previewing the uploaded picture
//adding converted picture to the original <input type="file">
let fileInputElement = $(input)[0];
let container = new DataTransfer();
let file = new File([resultBlob], "heic"+".jpg",{type:"image/jpeg", lastModified:new Date().getTime()});
container.items.add(file);
fileInputElement.files = container.files;
console.log("added");
})
.catch(function (x) {
console.log(x.code);
console.log(x.message);
});
}
}
$("#input").change(function() {
convertHeicToJpg(this);
});
What I am doing is converting the heic picture to jpg, then previewing it.
After that I add it to the original input. Server side will consider it as an uploaded jpg.
Some delay can appear while converting, therefore I placed a loader gif while uploading.
The heic2any js library helped me accomplish this (https://github.com/alexcorvi/heic2any/blob/master/docs/getting-started.md)
On the client side, I converted the picture, then gave it to the server input. The server sees it as it was originally uploaded as PNG.
$('#files').on('change' , function(){
var total_file=document.getElementById("files").files.length;
for(var i=0;i<total_file;i++)
{
files = event.target.files[i];
var fileName = files.name;
var fileNameExt = fileName.substr(fileName.lastIndexOf('.') + 1);
objURL = URL.createObjectURL(event.target.files[i]);
if(fileNameExt == "heic") {
objURL = await convertHeicToJpg(input , i);
}
})
async function convertHeicToJpg(input , i)
{
var blobfile = $(input)[0].files[i]; //ev.target.files[0];
let blobURL = URL.createObjectURL(blobfile);
// convert "fetch" the new blob url
let blobRes = await fetch(blobURL)
// convert response to blob
let blob = await blobRes.blob()
// convert to PNG - response is blob
let resultBlob = await heic2any({ blob })
console.log(resultBlob)
var url = URL.createObjectURL(resultBlob);
let fileInputElement = $(input)[0];
let container = new DataTransfer();
let file = new File([resultBlob], "heic"+".png",{type:"image/png", lastModified:new Date().getTime()});
container.items.add(file);
fileInputElement.files[0] = container.files;
uploadFile(container.files);
console.log("added");
console.log(url);
return url ;
}
function uploadFile(files)
{
console.log(files);
var error = '';
var form_data = new FormData();
for(var count = 0; count<files.length; count++)
{
var name = files[count].name;
var extension = name.split('.').pop().toLowerCase();
form_data.append("files[]", files[count]);
}
$.ajax({
url:"<?php echo base_url(); ?>Property/upload",
method:"POST",
data:form_data,
contentType:false,
cache:false,
processData:false,
dataType:'JSON',
beforeSend:function(){
//..processing
},
success:function(data)
{
alert('image uploade')
}
})
}

Binding Images to Image placeholder in repeater

I have a repeater that loads info from SQLite and works well. The user has options to take photos which are stored both in their photo library and in a temp folder. On reloading the page I need to reload the images to for a sliding gallery of thumbnails under the relevant section in the repeater.
The Image repeater is defined as
<Repeater items="{{ images }}" id="{{ repeaterphotoid }}">
<Repeater.itemTemplate>
<Image src="{{localurl}}" width="75" height="75" visibility="{{photoevidence === 'y' ? 'visible' : 'collapse'}}" />
</Repeater.itemTemplate>
</Repeater>
And my code is
exports.takePic = function(args){
var page = args.object;
camera.requestPermissions().then(
function success(){
var livesite = appSettings.getString("livesite");
var images=[];
var whichcamera = args.object;
var options = {saveToGallery: true, keepAspectRation: true, height: 1024 };
var gallery = args.object.page.getViewById("images-"+whichcamera.id);
var source = new imageSourceModule.ImageSource();
camera.takePicture(options).then(function(imageAsset){
var img = new imageModule.Image();
source.fromAsset(imageAsset).then((imageSource) => {
var auditDB = new sqlite("my.db", function(err, db){
if (err){
alert("Failed to open the database", err);
} else {
var tempfilename = livesite+"-"+whichcamera.qid+"-";
db.all("SELECT filename FROM images WHERE filename LIKE '"+tempfilename+"%'").then(rows =>{
//console.log("Images rows="+rows.length+1);
if (rows.length == 0){
imageCount = 1;
}
else
{
imageCount = rows.length+1;
}
var livesite = appSettings.getString("livesite");
// var path = filesystem.path.join(filesystem.knownFolders.documants().path,"photos")
var folder = filesystem.knownFolders.documents();
var filename = livesite+"-"+whichcamera.qid+"-"+imageCount+".jpg";
var imgPath = filesystem.path.join(folder.path,filename);
var saved = imageSource.saveToFile(imgPath,"jpg");
if (saved){
var livesite = appSettings.getString("livesite");
var liveaudit = appSettings.getString("liveaudit");
db.execSQL("INSERT INTO images (localurl,remoteurl,syncd,siteid,filename,question) VALUES(?,?,?,?,?,?)",[imgPath,'-','n',livesite,filename,whichcamera.qid])
var imageList = [];
var tempfilename = livesite+"-"+whichcamera.qid+"-";
var imageSQL = "SELECT localurl,remoteurl,filename FROM images WHERE filename LIKE '"+tempfilename+"%'";
db.all(imageSQL).then(rows =>{
for (var row in rows) {
imageList.push({
localurl: rows[row][0],
filename: rows[row][2]
});
}
const imagesource = fromObject({
images: imageList
});
imagesource.set = ("images", imageList);
var imageholder = args.object.page.getViewById("repeat_"+whichcamera.id);
imageholder.bindingContext = imagesource;
});
};
});
};
});
});
}).catch(function (err) {
alert("Camera Error "+err.message);
})
//alert("Taking Pic with camera "+whichcamera.id);
},
function failure(){
alert("You must allow this app access to the camera and your photos library.")
});
}
Binding to the questions works as expected but I cannot bind the images to the image repeater, nothing happens. Obviously missing something but going code blind.

How to make an id= from an XML call give a link to what its calling?

One of my API calls gives a youtube link and I want the link to be clickable and open on another tab, but nothing is working
this is mode code HTML:
//the id produces a youtube link that that can be clicked, but if I add the id to the href, then it wont work.
<a href="" target="_blank">
<p id="strYoutube2"></p>
</a>
my js code:
//this is my XML call, if theres another .link function other than .innerXML for the youtube link, maybe that can be the issue, but I cant find anything online.
function getPosts() {
let xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.themealdb.com/api/json/v1/1/random.php', true);
console.log(xhr.readyState);
xhr.send();
xhr.onreadystatechange = () => {
if (xhr.readyState == 4 && xhr.status == 200) {
let response = JSON.parse(xhr.responseText);
console.log('response below:')
console.log(response);
console.log(response.meals[0].strMealThumb);
document.getElementById('strMeal').innerText = response.meals[0].strMeal
document.getElementById('strCategory').innerText = response.meals[0].strCategory
document.getElementById('strArea').innerText = response.meals[0].strArea
document.getElementById('strTags').innerText = response.meals[0].strTags
document.getElementById('strYoutube').innerHTML = response.meals[0].strYoutube
document.getElementById('strMealThumb').src = response.meals[0].strMealThumb
}
}
}
The HTML element with id strYoutube does NOT exist in you provided code:
document.getElementById('strYoutube').innerHTML = response.meals[0].strYoutube
For achieve what you're triyng to do, you can change your code as follows:
Check that I set an img HTML element with a predefined width and height.
Check the working jsfiddle here too:
// This is your function for get the posts of the given API URL.
function getPosts() {
let xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.themealdb.com/api/json/v1/1/random.php', true);
console.log(xhr.readyState);
xhr.send();
xhr.onreadystatechange = () => {
if (xhr.readyState == 4 && xhr.status == 200) {
let response = JSON.parse(xhr.responseText);
console.log('response below:')
console.log(response);
console.log(response.meals[0].strMealThumb);
// Comented due these HTML elements aren't here.
//document.getElementById('strMeal').innerText = response.meals[0].strMeal
//document.getElementById('strCategory').innerText = response.meals[0].strCategory
//document.getElementById('strArea').innerText = response.meals[0].strArea
//document.getElementById('strTags').innerText = response.meals[0].strTags
//document.getElementById('strYoutube').innerHTML = response.meals[0].strYoutube
//document.getElementById('strMealThumb').src = response.meals[0].strMealThumb
// Here I set the values to your HTML elements:
// "strYoutube" is the HTML anchor element "<a href>".
document.getElementById('strYoutube').href = response.meals[0].strYoutube;
// "myImg" is the HTML image element "<img src>".
document.getElementById('myImg').src = "https://www.themealdb.com/images/media/meals/ysqupp1511640538.jpg";
document.getElementById('myImg').alt = response.meals[0].strMeal;
document.getElementById('myImg').title = response.meals[0].strMeal;
}
}
}
// Call your function and set the values ion the HTML elements:
getPosts();
<a href="" target="_blank" id="strYoutube">
<p id="strYoutube2">
<img src="#" id="myImg" alt="image" title="" style="width: 150px; height: 150px;" />
</p>
</a>

In FF45 FormData with empty file input didnt set Content-Type

Bugs started when clients had migrating to FF 45. They tryed to submit forms with empty file inputs and it fail.
I detected that, if you submit form by AJAX with FormData, and it have empty file input - FF will not set Content-Type: application/octet-stream
I created minimal script to demonstrate this bug:
var fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.name = 'fileData';
var form = document.createElement('form');
form.method = 'post';
form.enctype = 'multipart/form-data';
form.appendChild(fileInput);
var xhr = new XMLHttpRequest();
xhr.open("POST", "/url");
xhr.send(new FormData(form));
I use standart FF45 on windows.
I didnt find any information about this bug, and use hack: delete empty file inputs before submited id:
var fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.name = 'fileData';
var form = document.createElement('form');
form.method = 'post';
form.enctype = 'multipart/form-data';
form.appendChild(fileInput);
// Filter empty file inputs
var childNodes = form.querySelectorAll('input[type=file]');
for (var i=0;i<childNodes.length;i++) {
if (childNodes[i].files.length === 0) {
childNodes[i].parentElement.removeChild(childNodes[i]);
}
}
var xhr = new XMLHttpRequest();
xhr.open("POST", "/url");
xhr.send(new FormData(form));

Drawing Uploaded Image(with Ajax) to Canvas

I am using jQuery AJAX Form plugin to upload images without refreshing the page. It is ok if I show the uploaded image within an image tag( setting src to uploaded image path.) However, I cannot draw that uploaded image on a canvas element. I actually do not know what the problem is.
if (isset($_FILES["image"]["name"]) && !empty($_FILES["image"]["name"])) {
$filename = $_FILES["image"]["name"];
$tmpname = $_FILES["image"]["tmp_name"];
$location = "uploads/";
move_uploaded_file($tmpname, $location.$filename);
echo $location.$filename;
} else {}​
var canvas = document.getElementById("canv");
var contex = canvas.getContext("2d");
var img = new Image();
img.src = responseText;
img.onload = function(){ contex.putImageData(img, 0, 0); }
Above is my callback function(inside) when I call when the Ajax process is done. Thanks for any helpful answer.
UPDATE: FULL CODE
<html>
<head>
<script src="jq171.js"></script> <!--jQuery-->
<script src="jqform.js"></script> <!--jQuery ajax Form plugin-->
<script>
$(document).ready(function(){
$("#myform").ajaxForm(function({success: updateSrc}){
});
});
function updateSrc(responseText){
var canvas = document.getElementById("canv");
var contex = canvas.getContext("2d");
var img = new Image();
img.src = responseText;
img.onload = function(){ contex.drawImage(img, 0, 0); }
}
</script>
</head>
<body>
<form id="myform" action="this.php" method="post" enctype="multipart/form-data" >
<canvas id="canv" width="400px" height="400px"></canvas>
<input type="file" name="image"/>
<input type="submit"/>
</form>
</body>
</html>
Is there a reason why you don't just do an automatic request for the image?
As in leave the updateSrc as
function updateSrc(imagePath){
var canvas = document.getElementById("canv");
var contex = canvas.getContext("2d");
var img = new Image();
img.src = imagePath;
img.onload = function(){ contex.drawImage(img, 0, 0); }
}
Where the imagePath is the path to the image file.
for example:
updateSrc("images/example_image.jpg");
So jquery ajax request doesn't even need to be written.
You are using wrong function.
context.putImageData(imgData,x,y);
it takes image data, which is not an image object but raw pixel data. Instead, you want to use :
context.drawImage(img,0,0);
It should solve your problem

Resources