I am developing a site using Zend PHP framework. On a page I have a chart created with Google Chart API - https://developers.google.com/chart/. I would like to add a button to allow the user to download the chart as a PDF file (essentially convert the chart to an image and embed it in a PDF).
I have been able to convert the google chart to an image using a javascript function that generates the image data string - http://www.battlehorse.net/attach/topics/charts/google_charts_to_image.html
function getImgData(chartId) {
var chartContainer = document.getElementById(chartId);
var chartArea = chartContainer.getElementsByTagName('iframe')[0].
contentDocument.getElementById('chartArea');
var svg = chartArea.innerHTML;
var doc = chartContainer.ownerDocument;
var canvas = doc.createElement('canvas');
canvas.setAttribute('width', chartArea.offsetWidth);
canvas.setAttribute('height', chartArea.offsetHeight);
canvas.setAttribute(
'style',
'position: absolute; ' +
'top: ' + (-chartArea.offsetHeight * 2) + 'px;' +
'left: ' + (-chartArea.offsetWidth * 2) + 'px;');
doc.body.appendChild(canvas);
canvg(canvas, svg);
var imgData = canvas.toDataURL("image/png");
canvas.parentNode.removeChild(canvas);
return imgData;
}
I have also downloaded a free PHP class to handle generating the PDF - http://www.fpdf.org/
I have been able to use an ajax function to pass the image data string to a zend controller. I can then save the image locally and use it to build a PDF file and save that locally too.
//store the image locally
$data = substr($image,strpos($image,",")+1); //removing the "data:image/png;base64," part
file_put_contents ('downloads/'.$title.'.png', base64_decode($data));
// create PDF document
$pdf = new FPDF();
$pdf->AliasNbPages();
$pdf->AddPage();
$pdf->Image('downloads/'.$title.'.png',10,6,30);
//destroy the local copy of the image
fclose('downloads/'.$title.'.png');
unlink('downloads/'.$title.'.png');
//save the PDF document
$pdf->Output('downloads/'.$title.'.pdf');
I am now stuck because I cannot find a way to present the PDF file for downloading. I need to use an Ajax request to generate the PDF as the image data string is too long for a standard URL. So I think I need to redirect the user to the download link for the file after it has been generated (and then delete it again afterwards).
Does anyone know how I can serve the file for download, if I enter the file path into my browser I get a path not found error (e.g. "MyApp/public/downloads/myChart.pdf"). I have read in a few places how to set the header and body of the response in the controller but nothing has worked so far.
Whe you are generating the download link. Why don't you replace yourpath/public with domain.com? Assuming that ur PDF is generated In the directory public/downloads/blahblah
Possibly the next step would be lik
$path = 'downloads/'.$title.'.pdf';
Header("Location: http://domain.com.$path");
Now when the user calls this script file , using Ajax, the PDF will be generated and the location will be transferred to pdf's path!
Related
In javascript, I read the file data by binding the on-change method to the file input and saving the file data into another input using the following code
$("#release_cover_custom").on('change', function (evt) {
var files = evt.target.files; // FileList object
// Loop through the FileList and render image files as thumbnails.
for (var i = 0, f; f = files[i]; i++) {
// Only process image files.
if (!f.type.match('image.*')) {
continue;
}
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function (theFile) {
return function (e) {
$("#release_cover_custom_data").val(e.target.result);
};
})(f);
// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
});
why i use the above code?, to store the image data, because i have a form where i provide settings for the email template that would be sent later and there i have to provide the background image to be used inside the email, i need to preview the email with all the settings and along with the background image provided to upload before saving the form or uploading the image, so i read the image data, save it to an input and then open a modal window to preview email and post all the necessary variables there including the image data which is then used in the following way inside the css to apply the background-image like below in my php view file
background-image:url('" . $background_image . "') !important;
Now i want to do the achieve the same thing via php, means if i have the image saved to a path and i want to read the image data and use it in the same way i did using javascript to futher pass it to the css property,
i tried to use base64_encode(file_get_contents('path/to/file'))
but the encoding seems to be different for the image data, as the background image is not shown should i be using some other method to achieve it in php.
#quagaar reply (on the question) helped me solve the problem and replaced the following
$background_image=base64_encode(file_get_contents('/path/to/file'));
with
$background_image='data:image/png;base64,'.base64_encode(file_get_contents('/path/to/file'));
and everything works fine as expected.
EDIT:
between i was dealing with images only and if you are working with Images only and you need mime type (e.g. for headers, or like my case), then this is a fast and reliable technique:
$file = 'path/to/image.jpg';
$image_mime = image_type_to_mime_type(exif_imagetype($file));
It will output true image mime type even if you rename your image file.
What I am doing
Generating a dynamic image via javascript based on some variables specified in the query string. I am using this in a PHP Website.
What I need
The point here is I want to send this dynamically generated image in javascript to be displayed on the page as Image Header.
What I am using
PHP with APACHE Server (wamp)
Similar example of what I require
http://chart.googleapis.com/chart?cht=p3&chd=t:60,40&chs=250x100&chl=Hello|World
This is a Google Chart API, upon hitting the above URL, it returns you a PNG image based on the parameters specified in the Query String.
I have tried a lot, but yet unable to reach the success point.
Just, to show you what I am doing here is the Code
My Code Portion
/*
Logic to generate a canvas based on some parameters goes here
*/
// Canvas to Image
var img = canvas.toDataURL("image/png");
/*
My goal is to set this image to header of the page,
so that when the page is hit, an image is returned,
just like the Google Chart API thing mentioned above
*/
Create a javascript variable like this:
var monthly ="value to pass";
var recent ="value to pass";
var imgURL="http://YOURSITEURL/FOLDER/app1?monthly="+monthly+"&recent="+recent+"&likes="+likes;
Or:
var image = document.createElement("img");
image.src ="http://117.204.247.139:8084/myapps/app?monthly="+monthly+"&recent="+recent+"&likes="+likes;
I am not completely sure If I understand what you want. But on the PHP side you can
generate a PNG or JPEG file with a library like GD or Imagemagick.
(http://php.net/manual/en/book.image.php)
You can then send the data back to the client by setting the correct header, for PNG:
<?php
header("Content-Type: image/png");
ob_start();
echo $pngdata; // the binary data
ob_end_flush();
I'm having a problem finding if this is even possible (no info anywhere to be found).
Is it possible to EXTRACT a frame (thumbnail) during the video upload?
Extract using jscript is also an option if it's possible to extract user side.
Thanks for the help!
Fast forward almost five years since this question was posted, and the answer is now a yes!
Live demo
How to extract a frame during video upload using JavaScript
Before showing code, this is what we'll do:
Set an event handler on the input element that will take the video to be uploaded
When a file is selected from the file system, use the URL object to create a url to the local video file.
Load that URL into a video element.
When the video has loaded into memory, draw a frame on a canvas object.
Now export the frame rendered on the canvas into an image element (or optionally send that image to your server as a data url).
<input type="file" id="upload"/>
<img id="thumbnail"/>
<script>
var input = document.getElementById('upload');
var img = document.getElementById('thumbnail');
input.addEventListener('change', function(event){
var file = this.files[0];
var url = URL.createObjectURL(file);
var video = document.createElement('video');
video.src = url;
var snapshot = function(){
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
img.src = canvas.toDataURL('image/png');
video.removeEventListener('canplay', snapshot);
};
video.addEventListener('canplay', snapshot);
});
</script>
I don't think there is a good way to do that in php. (https://stackoverflow.com/a/1309425/1488032)
If it is not just some webspace that you have rented but have the rights to install and run other software on the server I would suggest using something like ffmpeg and calling it from within php using system(), passthru() or exec() to extract what you want and do the rest of the processing in php again.
I'm running a browser game that relies on svg images embedded in xhtml but some browsers (especially mobile ones) don't support the full svg syntax. In this case I use such a system() call to do svg-to-png conversion using imagemagick's convert binary and display the result on my page.
system("echo '$svgString' | convert svg:- png:- | base64");
I suppose you have to fall back to something similar.
Here's some information on extracting frames using ffmpeg:
http://ubuntuforums.org/showthread.php?t=1141293
Javascript: no.
During upload: no.
Once you've uploaded, yes.
"Dev" provided the right link in the comments, but what you should do is save the video to your server and then run ffMpeg to grab the image. You can download ffMPEG here: http://ffmpeg.org/download.html (grab hte build you need if you're not confident on building it yourself - there are Linux and Windows builds).
The documentation is here: http://ffmpeg.org/ffmpeg.html but there is a slightly easier to read tutorial at http://linuxers.org/tutorial/how-extract-images-video-using-ffmpeg for grabbing an image.
Note: there is a PHP extension clled "phpFFMPEG" but I suggest you don't use it. Simply run the desired commands through "exec()" in PHP. Check for error return values as you can only run ffMPEG once per CPU core, so if you try it twice at the same time it might fail - either queue the actions or try again if it fails.
First, you need to select a program to extract the frame. ffmpeg is commonly used for this. Whatever you pick, it needs to be able to work with partial file contents.
php scripts dont start executing until after the entire file upload has completed, but php recently got a feature so that a different php script can be executed during the file upload, and will be able to get at uploading scripts data(the filename is the thing of interest to you).
http://php.net/manual/en/session.upload-progress.php
Then, basically call the external program to extract the frame from the monitoring script, using the temp file name being uploaded in the upload handling script.
to summarize:
upload the file to upload.php.
monitor.php will get the temp file name being uploaded in upload.php, and extract the frame.
Basically, I took rodrigo-silveira answer provided in this thread and modified it for my use and now the solution works like a charm. Even I was trying to upload the video thumbnail/poster of a video that a user wishes to upload and save the video and the thumbnail in a folder. Also, I didn't want to use ffmpeg.
Here is what I did: In the upload file called "upload.php" I have the following code with slight modification to rodrigo-silveira's solution above:
upload.php:
<input type="file" id="upload"/>
<img id="thumbnail"/>
<form action="action_page.php" method="post" target="_blank">
<input type="hidden" id="mytext" name="mytext" >
<input type="submit" value="Submit">
</form>
<script>
var input = document.getElementById('upload');
var img = document.getElementById('thumbnail');
input.addEventListener('change', function(event){
var file = this.files[0];
var url = URL.createObjectURL(file);
var video = document.createElement('video');
video.src = url;
var snapshot = function(){
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = 350;
canvas.height = 250;
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
img.src = canvas.toDataURL('image/png');
document.getElementById("mytext").value = img.src;
video.removeEventListener('canplay', snapshot);
};
video.addEventListener('canplay', snapshot);
});
</script>
Both the HTML part and the JavaScript above are within the upload.php's body tag.
Now on to the action_page.php file:
<?php
$data = $_POST['mytext'];
$file = "photos/file".time().".png";
$uri = substr($data,strpos($data, ",") + 1);
file_put_contents($file, base64_decode($uri));
?>
Save both PHP files in the same folder and create another folder called "photos" in that folder. Your video thumbnail/poster image from a video that is selected in the upload.php page gets saved in the "photos" folder as png file. (Note: this solution does not upload the video, just the video thumbnail. But that is straight forward from here on.)
I draw something with html5-canvas. then i want to save it, and when the page is loaded again, I want to load the image I saved back to the canvas. I succeed with saving the data into a file in the server, but for some reason it's a strange file that can't open by ant software, and ofcourse not by my canvas. I save it as png base64, but i tried other things that didn't work.
javascript code:
function save(){ //saves the canvas into a string as a base64 png image. jsvalue is sent to the server by an html form
var b_canvas = document.getElementById("a");
var b_context = b_canvas.getContext("2d");
var img = b_canvas.toDataURL("image/png");
document.classic_form.jsvalue.value = img;
}
// opens the image file and displays it on the canvas
var canvas = document.getElementById("a");
var context = canvas.getContext("2d");
var img = new Image();
img.src = "backpicture.png";
img.onload = function() {
context.drawImage(img, 0, 0);
};
php code:
<?php
$str=$_POST['jsvalue'];
$file=fopen("backpicture.txt","w");
if(isset($_POST['submit']))
fwrite($file,$str);
fclose($file)
?>
it creates the file, but shows nothing on the canvas when I load the page again.
I also tried to use Canvas2Image.saveAsPNG(), but it still didn't work.
can you please help?
thanks!
In order to save the file properly you need to decode the base64 data (and save as png):
file_put_contents('backpicture.png', base64_decode($str));
This:
.toDataURL("image/png");
Will give you something like this:
image/png;base64,iVBORw0K...[base64encoded_string]...
As #Variant said, you need to base64_decode it, but, ignoring "image/png;base64,"
This should work:
file_put_contents('backpicture.png',base64_decode(substr($str,22)));
I'm trying to save a snapshot of a component in my flex app that is then sent to a php script to be saved and then spit back out into the browser window. I can't seem to get this to work.
Here's my FlashBuilder code:
private function saveImage():void {
var parameters:String = "snapshot=" + takeSnapshot(this);
var variables:URLVariables = new URLVariables(parameters);
var submit:URLRequest = new URLRequest("SaveImage.php");
submit.data = variables;
submit.method = URLRequestMethod.POST;
navigateToURL(submit,"_self");
}
private function takeSnapshot(component:IBitmapDrawable):String {
return ImageSnapshot.encodeImageAsBase64(ImageSnapshot.captureImage(component));
}
Here's my experimental PHP code:
$binaryData = base64_decode($_POST["snapshot"]);
$file = "mydirectory/tmp.png";
file_put_contents($file, $binaryData);
header("Content-type: image/png");
die($binaryData);
That generates the following output (where {path to image} is the url where the image was saved):
The image “{path to image}” cannot be
displayed, because it contains errors.
It does save a .png file to that directory but it's blank, there's nothing there but it's dimensions are correct. I've confirmed that the snapshot works by loading it in the app with a swfLoader component right after the snapshot is taken so I know the image is good before it's sent to the server.
Use the PNGEncoder instead.