My django website aims at allowing users to combine different clothing picture on one single canvas.
However, the saved image is blank.
I have applied one fiddle, please see here.
I've used the methods recommended by some forums.
Here is the views.py
#csrf_protect
#csrf_exempt
def savewearingimg(request):
imgEncodeString = request.POST.get('imgBase64')
if request.method == 'POST' and request.is_ajax():
singleItemNames = request.POST.getlist('singleItemNames[]')
saveWearingName = request.POST.get('saveWearingName') #string
positionsX = request.POST.getlist('positionsX[]')
positionsY = request.POST.getlist('positionsY[]')
userWidths = request.POST.getlist('sizes[]')
imgEncodeString = request.POST.get('imgBase64').partition(",")[2]#for header removing
img64Data = base64.b64decode(imgEncodeString) #other decoding fundctions failed
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
preFileStr = os.path.join(BASE_DIR, "media\\photos\\wearing\\")
poFileStr=str(request.user)+'_itemName_'+saveWearingName+'.jpg'
filename = preFileStr +poFileStr
with open(filename, 'wb') as f:
f.write(img64Data)
return render(request,'combinewearing.html')
And here is part of the javascript combinewearing.js
$(function() {
canvas = document.getElementById('save-canvas');
context = canvas.getContext('2d');
});
$('#saveWearingBtn').click(function(){
drawToSave(alreadyPutImg,originalWidths);
});
function drawToSave(alreadyPutImg,originalWidths){
loadImagesMike(sources, function(images_) { //the original author is Mike
for(var i=0; i<ImgPutArr.length; i++ ){
var img_iter = ImgPutArr[i];
context.drawImage(images_[i],img_iter.x,img_iter.y,img_iter.w,img_iter.h);
console.log('images_[i]: '+images_[i] );//[object HTMLImageElement]
i++;
}
});
var myDataURL = canvas.toDataURL();
$.ajax({
type: "POST",
url: "/savewearingimg/",
data: {
'csrfmiddlewaretoken': "{{ csrf_token }}",
'imgBase64': myDataURL,
'singleItemNames': alreadyPutName,//array storing what users have added to the canvas
'saveWearingName':$('#saveWearingName').val(), //end-users can customized his/her desired wearing title
'positionsX':positionsX, //position array storing every clothing pictures
'positionsY':positionsY,
'sizes':sizes,
},
}).done(function(o) {
alert('saved');
console.log('saved');
});/*end ajax*/
}
/*sources is an array storing all the user-selected pictures absolute path*/
function loadImagesMike(sources, callback) {
var images = [];
var loadedImages = 0;
var numImages = 0;
// get num of sources
for(var src in sources) {
numImages++;
}
for(var src in sources) {
images[src] = new Image();
images[src].onload = function() {
if(++loadedImages >= numImages) {
callback(images);
}
};
images[src].src = sources[src];
}
}
There is no error message. Only the image is blank.
However, if I follow the same steps and same string as this linksuggests, the image would not be blank.
So I suppose that the problem is due to the string's content. My failed
string content links to this google doc link(Correct me if I'm wrong, thank you.)
I've just found that this rectangle will show up in the image....
So what should I adjust?
context.rect(20, 20, 150, 100);
context.stroke();
I have solved this problem by moving THIS PART to the interior of the loadImagesMike() function (inside drawToSave())
THIS PART---->
var myDataURL = canvas.toDataURL();
$.ajax({
type: "POST",
url: "/savewearingimg/",
data: {
'csrfmiddlewaretoken': "{{ csrf_token }}",
'imgBase64': myDataURL,
'singleItemNames': alreadyPutName,//array storing what users have added to the canvas
'saveWearingName':$('#saveWearingName').val(), //end-users can customized his/her desired wearing title
'positionsX':positionsX, //position array storing every clothing pictures
'positionsY':positionsY,
'sizes':sizes,
},
}).done(function(o) {
alert('saved');
console.log('saved');
});/*end ajax*/
THIS PART is moved after the for loop, and it is inside the loadImagesMike() function.
Related
I convert the current mxGraph the user creates into XML which is stored in the database (ajax.js). I return this in my views as a JSONResponse to my ajax request (views.py).
The data stored in the database saves, as I have checked in the Django administration page and the xml gets updated per save button.
This is all working fine, however the issue is that when I refresh the page the graph created does not stay on the page.
ajax.js
var button = mxUtils.button('Save', function()
{
//var url = "{%url'login'%}"
//var url = "{% url 'myapp:productdetail' %}";
//location.href = '/saveData/'
var encoder = new mxCodec();
var node = encoder.encode(graph.getModel());
var xml = mxUtils.getPrettyXml(node);
var csrftoken = getCookie('csrftoken');
$.ajax({
type: "POST",
url: "/saveData/",
data: { "xml": xml},
headers:{
"X-CSRFToken": csrftoken
},
success: function(data){
//console.log("data" + data[0])
//console.log(graph)
//var xmlDoc = data[0]
var xmlDoc = mxUtils.parseXml(data[0]);
//var xmlDoc = mxUtils.load("/saveData/").getXml();
//console.log("xmlDoc " + xmlDoc)
var node = xmlDoc.documentElement;
//console.log("node " + node)
var dec = new mxCodec(node.ownerDocument);
//console.log("dec " + dec)
//console.log("graph model " + graph.getModel())
dec.decode(node, graph.getModel());
}
});
views.py
def saveData(request, user):
if request.method == "POST":
#Get user profile
member = Member.objects.get(username=user)
#Get XML data once user presses save
#xmlData = request.POST['xml']
member.data = request.POST['xml']
member.save()
print(member.data)
response = JsonResponse([
member.data
], safe = False);
#return render(request, 'fastcookapp/index.html', {"xmlData": member.data})
return HttpResponse(response, content_type="application/json")
return HttpResponse('POST is not used')
models.py
class Member(User):
data = models.TextField(null=True)
def __str__(self):
return self.username
P.S I have no clue why my JS is not coming in colour, I have added the javascript tag and it's not working... sorry in advance
I had to create an Ajax GET request and decode the mxGraph as done above.
I try this reference : https://github.com/blueimp/JavaScript-Load-Image
I try like this : https://jsfiddle.net/oscar11/gazo3jc8/
My code javascript like this :
$(function () {
var result = $('#result')
var currentFile
function updateResults (img, data) {
var content
if (!(img.src || img instanceof HTMLCanvasElement)) {
content = $('<span>Loading image file failed</span>')
} else {
content = $('<a target="_blank">').append(img)
.attr('download', currentFile.name)
.attr('href', img.src || img.toDataURL())
var form = new FormData();
form.append('file', currentFile);
$.ajax({
url:'response_upload.php',
type:'POST',
data:form,
processData: false,
contentType: false,
success: function (response) {
console.log(response);
},
error: function () {
console.log(error)
},
});
}
result.children().replaceWith(content)
}
function displayImage (file, options) {
currentFile = file
if (!loadImage(
file,
updateResults,
options
)) {
result.children().replaceWith(
$('<span>' +
'Your browser does not support the URL or FileReader API.' +
'</span>')
)
}
}
function dropChangeHandler (e) {
e.preventDefault()
e = e.originalEvent
var target = e.dataTransfer || e.target
var file = target && target.files && target.files[0]
var options = {
maxWidth: result.width(),
canvas: true,
pixelRatio: window.devicePixelRatio,
downsamplingRatio: 0.5,
orientation: true
}
if (!file) {
return
}
displayImage(file, options)
}
// Hide URL/FileReader API requirement message in capable browsers:
if (window.createObjectURL || window.URL || window.webkitURL ||
window.FileReader) {
result.children().hide()
}
$('#file-input').on('change', dropChangeHandler)
})
If I uploaded the image, the image saved in the folder still does not use the image that is in its orientation set. I want when I upload a picture, the image stored in the folder is the image that has been set its orientation
It seems that the currentFile sent via ajax is the unmodified currentfFile. How do I get the modified currentFile?
After some researching little bit I found the solution thanks to this great plugin https://github.com/blueimp/JavaScript-Canvas-to-Blob . ( canvas-to-blob.js )
This plugin will convert your canvas to a Blob directly server would see it as if it were an actual file and will get the new(modified) file in you $_FILES array. All you need is call toBlob on the canvas object (img). After that you would get your blob which you then can send in FormData. Below is your updated updateResults() function
function updateResults (img, data) {
var content
if (!(img.src || img instanceof HTMLCanvasElement)) {
content = $('<span>Loading image file failed</span>')
}
else
{
content = $('<a target="_blank">').append(img)
.attr('download', currentFile.name)
.attr('href', img.src || img.toDataURL())
img.toBlob(
function (blob) {
var form = new FormData();
form.append('file', blob, currentFile.name);
$.ajax({
url:'response_upload.php',
type:'POST',
data:form,
processData: false,
contentType: false,
success: function (response) {
console.log(response);
},
error: function () {
console.log(error)
},
});
},'image/jpeg'
);
result.children().replaceWith(content);
}
}
You want to change some things about image (dimensions, roataion etc) and upload it on to the server but the problem here is that ImageLoad plugin will give the modified image as an canvas means it won't modify the original file selected in
<input type="file" id="file-input">. Since you are sending the file input object in form.append('file', currentFile); your modified file wont get sent but just the original
How to fix?
This is particularity hard you (or plugin) cannot modify anything on <input type="file" id="file-input"> due to browser restrictions neither you can send canvas directly to the server so the only way (used and works great) is to send the data URI of the image as a regular text and then decode it on the server, write it to a file.You might also want to send the original file name since a data URI is pure content and doesn't hold file name
Change
form.append('file', currentFile);
To
form.append('file', img.toDataURL() ); // data:image/png;base64,iVBO ...
form.append('file_name', currentFile.name ); // filename
PHP
$img_data=substr( $_POST['file'] , strpos( $_POST['file'] , "," )+1);
//removes preamble ( like data:image/png;base64,)
$img_name=$_POST['file_name'];
$decodedData=base64_decode($img_data);
$fp = fopen( $img_name , 'wb' );
fwrite($fp, $decodedData);
fclose($fp );
Good luck!
I'm trying to send an image from user's computer using an input (file).
I resize the image using a canvas and then get a base64 string encoded via the toDataURL method of the canvas.
Then I send the encoded string to my server via an AJAX request. In PHP, I receive properly the POST data, but it fails when I want to use the base64_decode to save the encoded string into a file on my server.
CLIENT SIDE :
function upload_document(file){
var url_post_document = "url_to_server";
var type_img = file.type;
var reader = new FileReader();
reader.onload = function(evt){
var image = document.createElement('img');
image.onload = function (){
var canvas = document.createElement('canvas');
canvas.height = 40;
canvas.width = 40;
var ctx = canvas.getContext('2d');
ctx.drawImage(this, 0, 0, 40, 40);
var shrinked = canvas.toDataURL(file.type);
//console.log(shrinked);
$.ajax({
url: url_post_document,
type: 'POST',
xhrFields: {
withCredentials: false
},
data: {
"user_id": user_id,
"image": shrinked,
"image_type": type_img
},
success: function(data) {
console.log("RESPONSE");
console.log(data);
},
error: function() {
console.log("----- FAIL -----");
},
complete: function() {
console.log("----- REQUEST COMPLETED -----");
}
});
};
image.src = reader.result;
};
reader.readAsDataURL(file);
}
SERVER SIDE :
if(isset($_POST['user_id'])){
$extension = explode('/', $_POST['image_type']);
$extension = $extension[1];
define('UPLOAD_DIR', WP_CONTENT_DIR.'/uploads/userthumb/');
$imgBaseData = rtrim($_POST['image']);
$img = str_replace('data:'.$_POST['image_type'].';base64,', '', $imgBaseData);
$img = str_replace(' ', '+', $img);
$baseimage = base64_decode($img, true);
return $baseimage;
}
I tried to copy and past the base64 string got from the toDataURL method on an online base64decoder and it works, the image is displayed. But on the server, impossible to decode the string.
I would appreciate any help on this matter. Thanks in advance !
I am using jsPDF to create a PDF on client side, send it to my python server via ajax call, then send the PDF to myself via email. When I create the jsPDF object with some text:
var doc = new jsPDF();
doc.text(35, 25, "test");
It works, and I get the email with the populated PDF attached. When I try and add an image:
var doc = new jsPDF();
doc.text(35, 25, "test");
doc.addImage(imageDataURL, 0, 50);
The ajax call doesn't go through and I get an error. I have tried just having the image on the page, without the text, but the same error happens. My python controller isn't complaining, mainly because it isn't getting called. When I print the error to the console, it says the responseText is "", and status is 0.
When I download the created PDF with doc.save(), the PDF looks fine. It has the image and the text is the right positions.
My code looks like this:
Javascript:
checkout_button.addEventListener('click', function() {
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
var image = new Image();
image.src = curr_order.image_url;
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
context.drawImage(image, 0, 0, canvas.width, canvas.height);
var doc = new jsPDF();
doc.text(35, 25, "test");
doc.addImage(canvas.toDataURL('image/jpeg', 1), 'jpeg', 0, 50);
var pdf = doc.output();
//doc.save();
$.ajax('{{=URL('default', 'send_note_PDF')}}', {
data: {
pdf_data: pdf
},
Method: 'POST',
success: function () {
console.log('cool');
},
error: function (data) {
console.log('not cool');
console.log(data);
}
});
});
Python:
def send_note_PDF():
pdf_data = request.vars.pdf_data
file = open('test.pdf', 'w')
file.write(pdf_data)
file.close()
msg = MIMEMultipart()
msg['From'] = 'sending-email#gmail.com'
msg['To'] = 'receiving-email#gmail.com'
msg['Subject'] = 'PDF Test'
body = "test"
msg.attach(MIMEText(body))
file = open('test.pdf', 'rb')
part = MIMEApplication(file.read(), file.name)
part['Content-Disposition'] = 'attachment; filename="%s"' % file.name
msg.attach(part)
mail = smtplib.SMTP('smtp.gmail.com', 587)
mail.ehlo()
mail.starttls()
mail.login('sending-email#gmail.com', 'password')
mail.sendmail('sending-email#gmail.com', 'receiving-email#gmail.com', msg.as_string())
mail.close()
return 'ok'
Do I have to format the output of the doc before I pass it through ajax? I have tried stringifying it and parsing it on the python side. It works without the picture, but whenever that picture is added, it doesn't play nicely.
I'm trying export a string base64 that represents an image taken from canvas html5, this is the code in javascript:
var canvas1 = $("#canvas1")[0];
var ctx1 = canvas1.getContext('2d');
dataURL1 = canvas1.toDataURL();
Whit ajax I sent the image to server:
$.ajax({
type: "POST",
url: "/regiter_respuesta_agilidad/",
data:{
'imagen1': dataURL1,
}
});
In views.py of django I use base64.b64decode to export the string to image:
imagen1 = request.POST['imagen1']
image_data = base64.b64decode(imagen1)
imagene = ContentFile(image_data, 'imagen1.png')
answer = Answer(imagen=imagene)
In models.py I have:
class Answer(models.Model):
imagen = models.ImageField(upload_to=url)
The Problem is when the image is saved, the file imagen1.png is corrupted and I can't open it, Can someone help me with this problem?, or is there another way to do this? thank you very much.
I'm guessing you need to strip the data: off the Data URI returned by canvas.toDataURL();.
A quick google search found some code designed for parsing data uris in python https://gist.github.com/zacharyvoase/5538178 and another: dataurl.py
instead of this line: image_data = base64.b64decode(imagen1)
use this line : image_data = base64.b64decode(imagen1[22:] + b'=' * (-len(imagen1[22:]) % 4))