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.
Related
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.
I have a page that has jquery and the amazon SDK. There is text in an area box that the user can change. I successfully make the request to Amazon. I get back the PCM AudioStream (Int16Array). How do I then convert this stream to a downloadable PCM file? When the file downloads, the file is useless and can't be played. The file does have a size greater than 0, so that makes me believe there is data there.
<script>
AWS.config.region = 'us-east-1';
AWS.config.accessKeyId = 'CANDY';
AWS.config.secretAccessKey = 'CANES';
var polly = new AWS.Polly({apiVersion: '2016-06-10'});
var params = {
OutputFormat: 'pcm',
Text: 'Text from the textbox',
VoiceId: 'Joey',
SampleRate: '16000',
TextType: 'text'
};
polly.synthesizeSpeech(params, function(err, data) {
if (err){
console.log(err, err.stack); // an error occurred
} else {
var stream = new Int16Array(audioStream);
var arrayBuffer = stream.buffer;
var blob = new Blob([arrayBuffer], {type: 'audio/pcm'});
var url = URL.createObjectURL(blob);
.....set href for link to url.......
}
});
</script>
If you are sure the url object is correct (can you download it from a separate browser tab?), I would use JQuery to dynamically change your DOM, as per this answer How to change the href for a hyperlink using jQuery
This question is not answering my situation as it is not providing a solution, and I am wondering if now (by 2018) we have a better approach.
So the problem is I would like to call my server which is creating pdf file (not physically) and giving the contents of the file as stream to the http response. Now, with an ajax call to this web service, I want to display the returned data as a pdf file if possible.
function callProducePdf(webServiceUrl, resultAreaId){
var jqxhr = $.ajax({
type:"GET",
url: webServiceUrl
});
jqxhr.done(function(data){
//data contains the pdf in inputStream form
//how can I display the pdf in resultAreaId which is a div?
//if I do something like this it works but this is not what I want
var iframe = $('<iframe height="500px">');
iframe.attr('src', webServiceUrl);
resultAreaId.prepend(iframe, "<br>");
});
jqxhr.fail(function(){
//I have this function defined which is working fine
appendError(resultAreaId);
});
}
server side code:
#GetMapping("/producePdfWithDefault")
public ModelAndView producePdfWithDefault(HttpServletRequest request, HttpServletResponse response) {
Resource resource = new ClassPathResource("/path/a/static/pdf/file.pdf");
InputStream resourceAsStream;
try {
resourceAsStream = resource.getInputStream();
byte[] resourceInBytes = Base64.encodeBase64(IOUtils.toByteArray(resourceAsStream));
response.reset();
response.setContentType("application/pdf");
response.setHeader("content-disposition","inline; filename=documentPreview.pdf");
response.setContentLength(resourceInBytes.length);
OutputStream output = response.getOutputStream();
output.write(resourceInBytes);
output.flush();
output.close();
} catch (IOException e) {
response.setStatus(500);
}
return null;
}
Any help is much appreciated. Thank you..
I would do something like this...
...
jqxhr.done(function(data) {
var blob = new Blob([data]);
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = "<ANY_FILENAME_WITH_EXTENSION>";
link.click();
}),
...
(untested)
Client will download the file and open it in the default PDF reader.
You can use PDF.js to render your PDF into a canvas element.
The demo below is from their examples
// atob() is used to convert base64 encoded PDF to binary-like data.
// (See also https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/
// Base64_encoding_and_decoding.)
var pdfData = atob(
'JVBERi0xLjcKCjEgMCBvYmogICUgZW50cnkgcG9pbnQKPDwKICAvVHlwZSAvQ2F0YWxvZwog' +
'IC9QYWdlcyAyIDAgUgo+PgplbmRvYmoKCjIgMCBvYmoKPDwKICAvVHlwZSAvUGFnZXMKICAv' +
'TWVkaWFCb3ggWyAwIDAgMjAwIDIwMCBdCiAgL0NvdW50IDEKICAvS2lkcyBbIDMgMCBSIF0K' +
'Pj4KZW5kb2JqCgozIDAgb2JqCjw8CiAgL1R5cGUgL1BhZ2UKICAvUGFyZW50IDIgMCBSCiAg' +
'L1Jlc291cmNlcyA8PAogICAgL0ZvbnQgPDwKICAgICAgL0YxIDQgMCBSIAogICAgPj4KICA+' +
'PgogIC9Db250ZW50cyA1IDAgUgo+PgplbmRvYmoKCjQgMCBvYmoKPDwKICAvVHlwZSAvRm9u' +
'dAogIC9TdWJ0eXBlIC9UeXBlMQogIC9CYXNlRm9udCAvVGltZXMtUm9tYW4KPj4KZW5kb2Jq' +
'Cgo1IDAgb2JqICAlIHBhZ2UgY29udGVudAo8PAogIC9MZW5ndGggNDQKPj4Kc3RyZWFtCkJU' +
'CjcwIDUwIFRECi9GMSAxMiBUZgooSGVsbG8sIHdvcmxkISkgVGoKRVQKZW5kc3RyZWFtCmVu' +
'ZG9iagoKeHJlZgowIDYKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDEwIDAwMDAwIG4g' +
'CjAwMDAwMDAwNzkgMDAwMDAgbiAKMDAwMDAwMDE3MyAwMDAwMCBuIAowMDAwMDAwMzAxIDAw' +
'MDAwIG4gCjAwMDAwMDAzODAgMDAwMDAgbiAKdHJhaWxlcgo8PAogIC9TaXplIDYKICAvUm9v' +
'dCAxIDAgUgo+PgpzdGFydHhyZWYKNDkyCiUlRU9G');
// Loaded via <script> tag, create shortcut to access PDF.js exports.
var pdfjsLib = window['pdfjs-dist/build/pdf'];
// The workerSrc property shall be specified.
pdfjsLib.GlobalWorkerOptions.workerSrc = '//mozilla.github.io/pdf.js/build/pdf.worker.js';
// Using DocumentInitParameters object to load binary data.
var loadingTask = pdfjsLib.getDocument({
data: pdfData
});
loadingTask.promise.then(function(pdf) {
console.log('PDF loaded');
// Fetch the first page
var pageNumber = 1;
pdf.getPage(pageNumber).then(function(page) {
console.log('Page loaded');
var scale = 1.5;
var viewport = page.getViewport(scale);
// Prepare canvas using PDF page dimensions
var canvas = document.getElementById('the-canvas');
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
// Render PDF page into canvas context
var renderContext = {
canvasContext: context,
viewport: viewport
};
var renderTask = page.render(renderContext);
renderTask.then(function() {
console.log('Page rendered');
});
});
}, function(reason) {
// PDF loading error
console.error(reason);
});
<script src="//mozilla.github.io/pdf.js/build/pdf.js"></script>
<h1>PDF.js 'Hello, base64!' example</h1>
<canvas id="the-canvas"></canvas>
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 want to send my pdf ataching for mail, but need from help.
In my html page have link which voice cry function goPDF.
This is my function for generation on sreenshot(pdf).
$scope.goPDF = function (id, type) {
ID->id on my info for pdf.
TYPE->This is text on pdf = automoto.pdf
$scope.link = "#/invoice/" + id;
//Here get url to info for my pdf.
var invoicePDF = document.getElementById ('iFrame').contentWindow.document.getElementById ('sendPDF');
//Here get all content for my pdf.
//Here make convert from html to canvas and finish canvas to pdf.
$ ("#sendPDF").css ('background', '#fff');
html2canvas ($ (invoicePDF), {
onrendered: function (canvas) {
var pdf = new jsPDF ();
var marginLeft = 0;
var marginRight = 0;
pdf.addImage (canvas.toDataURL ("image/jpeg"), "jpeg", marginLeft, marginRight);
//pdf.save (type + '.pdf');
//Here save pdf in my PC
var outputt = pdf.output ();
//I do not where url on my pdf for ataching to mail.
}
});