I've created a simple wrapper class for a TCPDF example I got off the web.
My aim is to call the methods in the class in succession, then output a pdf file to a directory in my project.
The code worked fine when I had a version of it in one blob and calling it from a page. After putting it into a class it seems to hang/do nothing around the call to Output(). I cannot step into it when debugging in netbeans, and no error appears to be thrown.
In case it was a folder permissions issue I've run chmod on the output directory in question.
Here is the class:
<?php
define('IMAGE_DIR', '/home/user/NetBeansProjects/PDF_Quote/img/');
require_once('lib/tcpdf/tcpdf.php');
class PDF_Test extends TCPDF {
function __construct() {
parent::__construct(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
}
public function set_document_info($creator = '', $author = '', $title = '', $subject = '', $keywords = '')
{
$creator = PDF_CREATOR;
$author = 'Author';
$title = 'Title Example';
$subject = 'Subject Example';
$keywords = 'TCPDF, PDF, example, test, guide';
// set document information
$this->SetCreator($creator);
$this->SetAuthor($author);
$this->SetTitle($title);
$this->SetSubject($subject);
$this->SetKeywords($keywords);
}
public function header($logo_img = '', $title_text = '', $addit_text = '')
{
$logo_img = IMAGE_DIR . 'headerimg.png';
$title_text = 'the title';
$addit_text = 'additional text';
$this->SetHeaderData($logo_img, PDF_HEADER_LOGO_WIDTH, $title_text.' 001', $addit_text, array(0,64,255), array(0,64,128));
$this->setHeaderFont(Array(PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN));
}
public function footer($logo_img = '', $text = '')
{
$this->setFooterData(array(0,64,0), array(0,64,128));
$this->setFooterFont(Array(PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA));
}
public function set_default_monospaced_font($font = '')
{
if (strlen($font) === 0) { $font = 'courier'; }
$this->SetDefaultMonospacedFont($font);
}
public function set_margins($margin_left = '', $margin_top = '', $margin_right = '', $margin_header = '', $margin_footer = '')
{
$margin_left = PDF_MARGIN_LEFT; $margin_top = PDF_MARGIN_TOP; $margin_right = PDF_MARGIN_RIGHT;
$margin_header = PDF_MARGIN_HEADER; $margin_foot = PDF_MARGIN_FOOTER;
$this->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
$this->SetHeaderMargin(PDF_MARGIN_HEADER);
$this->SetFooterMargin(PDF_MARGIN_FOOTER);
}
public function set_auto_page_break($set = True, $margin = '')
{
$set = True;
$margin = PDF_MARGIN_BOTTOM;
$this->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
}
public function set_image_scale($img_scale_ratio = '')
{
$img_scale_ratio = PDF_IMAGE_SCALE_RATIO;
$this->setImageScale(PDF_IMAGE_SCALE_RATIO);
}
public function set_language_array()
{
if (#file_exists(dirname(__FILE__).'/lang/eng.php')) {
require_once(dirname(__FILE__).'/lang/eng.php');
$this->setLanguageArray($l);
}
}
public function set_font_subsetting($set = True)
{
$set = True;
$this->setFontSubsetting($set);
}
public function set_font($family = '', $style = '', $size = '', $fontfile = '', $subset = '', $out = True)
{
$family = 'dejavusans'; $size = '14';
$this->SetFont($family, $style, $size, '', $out);
}
public function add_page()
{
$this->AddPage();
}
// Can be html or just plain text
public function add_text_blob($html = '')
{
$html = '<h1>This is some stuff</h1><p style="background-color: green;">This is some content adhjdjasjd</p>';
$this->writeHTMLCell(0, 0, '', '', $html, 0, 1, 0, true, '', true);
}
public function output($path, $file_name)
{
$path = dirname(__FILE__) . '/pdfcache/'; //'/home/user/NetBeansProjects/PDF_Quote/pdfcache/';
$file_name = 'file_' . date('Y_m_d_H_i_s') . '.pdf';
try
{
$fp = $path . 'example1.pdf'; //. $file_name; //'/home/user/NetBeansProjects/PDF_Quote/pdfcache/example_001.pdf';
$this->Output($fp, 'F');
}
catch (exception $ex)
{
return $ex;
}
return $path . $file_name;
}
}
?>
Here is the code that calls the class in another php file:
require_once('PDF_Test.php');
$pdf = new PDF_Test();
$pdf->set_document_info();
$pdf->header();
$pdf->footer();
$pdf->set_default_monospaced_font();
$pdf->set_margins();
$pdf->set_auto_page_break();
$pdf->set_image_scale();
$pdf->set_language_array();
$pdf->set_font_subsetting();
$pdf->set_font();
$pdf->add_page();
$pdf->add_text_blob();
$pdf->output();
I haven't managed to find any similar issues in my googling, but I'm new to PHP, so I'm not sure if I'm overlooking anything glaringly obvious either.
I would recommend using the Output method in a way that it returns the PDF as binary string, so you can do whatever you want with it. This would be $pdfdoc = $pdf->Output('', 'S').
This way, you can still put the file to a path of your choice, but also dump it directly to the client, or attach it to an e-mail … and you can do a better error handling, because you have control over what TCPDF produces.
By the way, when you override a method in PHP, and you want to call the parent method, then you must use parent::METHOD(). Because you're actually overriding the header, footer, and output methods of TCPDF with yours (even if yours are lowercased).
Related
I am trying to generate a pdf file via the dompdf library (the displayed values come from a mysql database), and I have an encoding problem. I did a lot of research but without success.
The problem is that at each line break, a "/ n" is displayed.
I tried to use different functions html_entities_decode, nl2br and even str_replace ("/ n", "", $ str), but could not delete it.
The "/ n" is not registered in the database at the specified value. I looked in the source files dompdf and it does not come from there either.
A big thank you in advance for your responses !
CODE
use Barryvdh\DomPDF\Facade as PDF; // Barryvdh use dompdf
// function used
public function downloads($from, $type, $unique_id, $downloads, $dom, $do) {
$data['from'] = $from;
$data['type'] = $type;
$data['unique_id'] = $unique_id;
$data['title'] = 'PDF Generation';
//User Details
$userController = new userController;
$data['logeduser'] = $userController->logeduser();
$userpermissions = $userController->getpermissions();
//Notification Details
$notification = new notificationModel;
$data['notification_list'] = $notification->getAllRemainder();
//PDF Generation
$sales = new salesModel();
$data['offer_sav'] = $sales->getOfferSAVDetails($unique_id);
$data['offer_sav_products'] = $sales->getOfferSAVProductDetails($unique_id);
$data['offer_eg'] = $sales->getOfferSAVDetails($unique_id);
$data['offer_eg_component'] = $sales->getOfferEGComponent($unique_id);
$data['offer_eg_accessory'] = $sales->getOfferEGAccessory($unique_id);
$data['offer_eg_options'] = $sales->getOfferEGOptions($unique_id);
$data['sav_eg_without_sm'] = $sales->getSAVEGWithoutSM($unique_id);
//view()->share($data);
//return view('sales/pdfonly', $data);
$pdf = PDF::loadView('sales/pdfonly', $data);
//$view = view('sales/pdfonly', $data);
//$pdf = PDF::loadHTML($view);
if(!empty($_GET['print']))
return $pdf->stream('pdf_'.$from.'_'.$type.'.pdf', array("Attachment" => 0));
else
return $pdf->download('pdf_'.$from.'_'.$type.'.pdf');
}
// exemple of code output
{!! $eg->sales_offer_note2 !!} // = remarque1 <div>r<br> remarque2</div><div><br></div><div><br></div><div>
€
/*
OUTPUT
remarque1
r/n
emarque2
/n
/n
€
/n
*/
I use codeigniter and imap php currently developing project xampp. For some reason them embedded images not showing.
In my getBody() function I have this call back
$body = preg_replace_callback(
'/src="cid:(.*)">/Uims',
function($m) use($email, $uid){
//split on #
$parts = explode('#', $m[1]);
//replace local path with absolute path
$img = str_replace($parts[0], '', $parts[0]);
return "src='$img'>";
},
$body);
I get error
Question: How can I make sure it gets the images correct for the text/html body etc.
<?php
class Email extends MY_Controller {
private $enc;
private $host;
private $user;
private $pass;
private $mailbox;
private $mbox;
public function __construct() {
parent::__construct();
$this->enc = '/imap/ssl/novalidate-cert';
$this->host = '****';
$this->user = '****'; // email
$this->pass = '****'; // Pass
$this->mailbox = '{' . $this->host . $this->enc . '}';
$this->mbox = imap_open($this->mailbox, $this->user, $this->pass);
}
public function view() {
$this->data['message'] = $this->getBody($this->uri->segment(4));
$this->load->view('template/common/header', $this->data);
$this->load->view('template/common/nav', $this->data);
$this->load->view('template/mail/view', $this->data);
$this->load->view('template/common/footer', $this->data);
imap_close($this->mbox);
}
public function getBody($uid) {
$body = $this->get_part($uid, "TEXT/HTML");
// if HTML body is empty, try getting text body
if ($body == "") {
$body = $this->get_part($uid, "TEXT/PLAIN");
}
$email = $this->user;
//replace cid with full path to image
$body = preg_replace_callback(
'/src="cid:(.*)">/Uims',
function($m) use($email, $uid){
//split on #
$parts = explode('#', $m[1]);
//replace local path with absolute path
$img = str_replace($parts[0], '', $parts[0]);
return "src='$img'>";
},
$body);
return trim(utf8_encode(quoted_printable_decode($body)));
}
private function get_part($uid, $mimetype, $structure = false, $partNumber = false) {
if (!$structure) {
$structure = imap_fetchstructure($this->mbox, $uid);
}
if ($structure) {
if ($mimetype == $this->get_mime_type($structure)) {
if (!$partNumber) {
$partNumber = 1;
}
$text = imap_fetchbody($this->mbox, $uid, $partNumber, FT_PEEK);
switch ($structure->encoding) {
# 7BIT
case 0:
return imap_qprint($text);
# 8BIT
case 1:
return imap_8bit($text);
# BINARY
case 2:
return imap_binary($text);
# BASE64
case 3:
return imap_base64($text);
# QUOTED-PRINTABLE
case 4:
return quoted_printable_decode($text);
# OTHER
case 5:
return $text;
# UNKNOWN
default:
return $text;
}
}
// multipart
if ($structure->type == 1) {
foreach ($structure->parts as $index => $subStruct) {
$prefix = "";
if ($partNumber) {
$prefix = $partNumber . ".";
}
$data = $this->get_part($uid, $mimetype, $subStruct, $prefix . ($index + 1));
if ($data) {
return $data;
}
}
}
}
return false;
}
private function get_mime_type($structure) {
$primaryMimetype = array("TEXT", "MULTIPART", "MESSAGE", "APPLICATION", "AUDIO", "IMAGE", "VIDEO", "OTHER");
if ($structure->subtype) {
return $primaryMimetype[(int)$structure->type] . "/" . $structure->subtype;
}
return "TEXT/PLAIN";
}
}
Introduction
You are trying to convert an Email into a HTML Page.
An Email has multiple parts:
Headers
Text based email
HTML based email
Attachments
In the header you will find the Message-ID as well as other relevant metadata.
In order to convert an Email into a website you have to expose the HTML and the Attachments to the browser.
Each of the Parts has its own headers. When you have a url='cid:Whatever' you have to look for which part of the email hast that Content-Id header.
Serve the Email as a Web Page
You need to find wich Email part contains the HTML Body. Parse it and replace the CID URL's for your http://yourhost/{emailId} you already implemented that part so I will not add how to do it here.
Replace CID URL on HTML - Implementation
This is a prototype that may work for you.
$mailHTML="<html>All your long code here</html>";
$mailId="email.eml";
$generatePartURL=function ($messgeId, $cid) {
return "http://myhost/".$messgeId."/".$cid; //Adapt this url according to your needs
};
$replace=function ($matches) use ($generatePartURL, $mailId) {
list($uri, $cid) = $matches;
return $generatePartURL($mailId, $cid);
};
$mailHTML=preg_replace_callback("/cid:([^'\" \]]*)/", $replace, $mailHTML);
Find the part by CID
http://yourhost/{emailId}/{cid}
Pseudo code:
Load email
Find part by CID
Decode from Base64 or other Encoding used (Check Content-Transfer-Encoding header)
Serve the file as an HTTP Response
Which part has my CID image?
Iterate all email parts looking for the Content-ID header that match your CID value.
--_part_boundery_
Content-Type: image/jpeg; name="filename.jpg"
Content-Description: filename.jpg
Content-Disposition: inline; filename="filename.jpg"; size=39619; creation-date="Thu, 28 Dec 2017 10:53:51 GMT"; modification-date="Thu, 28 Dec 2017 10:53:51 GMT"
Content-ID: <YOUR CID WILL BE HERE>
Content-Transfer-Encoding: base64
Decode the transfer encoding and serve the contents as a regular http file.
Webmail implemented in PHP
RoundCube is a webmail implemented in PHP you can have a look how they do this: https://github.com/roundcube/roundcubemail/blob/master/program/lib/Roundcube/rcube_washtml.php
Note: My code it is not based in this solution.
This could be a very simple thing to do, but it is proving quite hard for me to achieve.
I am in the process of creating a custom plugin for elgg to build a library of things. I want to be able to upload an image when creating a new item.
Currently in my views/default/form/cust_plugin/save.php i have
elgg_view('input/file',array('name'=>'image','value'=>$image);
And in the actions/cust_plugin/save.php i have
$cust_plugin->image = $image;
but this doesn't work.
What am I missing, what am I doing wrong?
Thanks
To upload an image I use "file" plugin so I can manage it very simple.
In my function I call
//Load file library
elgg_load_library('elgg:file');
//Set multipart/form-data attribute on my form
$vars = array('enctype' => 'multipart/form-data');
$body_vars = file_prepare_form_vars();
//Create Array values to return
$return = array(
'title' => elgg_echo('gallery:title:add'),
'content' => elgg_view_form('elgg-gallery/uppa', $vars,$body_vars) //My form
);
My form is:
<div>
<label for="image_upload">Image upload</label>
<?php echo elgg_view('input/file', array('name' => 'img_upload')); ?>
</div>
And my action:
if (empty($_FILES['img_upload']['name']))
{
$error = elgg_echo('file:nofile');
register_error($error);
forward(REFERER);
}
//Make a file
$file = new FilePluginFile();
$file->subtype = "file";
// if no title, grab filename
if (empty($titolo))
$titolo = htmlspecialchars($_FILES['img_upload']['name'], ENT_QUOTES, 'UTF-8');
$file->title = $titolo;
$file->description = "description file";
$file->access_id = ACCESS_PUBLIC;
$file->owner_guid = elgg_get_logged_in_user_guid();
// we have a file upload, so process it
if (isset($_FILES['img_upload']['name']) && !empty($_FILES['img_upload']['name']))
{
//Generate filename
$prefix = "file/";
$filestorename = elgg_strtolower(time().$_FILES['img_upload']['name']);
$file->setFilename($prefix . $filestorename);
//Set Mimetype
$mime_type = ElggFile::detectMimeType($_FILES['img_upload']['tmp_name'], $_FILES['img_upload']['type']);
$file->setMimeType($mime_type);
//Set attributes
$file->originalfilename = $_FILES['img_upload']['name'];
$file->simpletype = file_get_simple_type($mime_type);
// Open the file to guarantee the directory exists
$file->open("write");
$file->close();
//Move file
move_uploaded_file($_FILES['img_upload']['tmp_name'], $file->getFilenameOnFilestore());
//Save file
$guid = $file->save();
//Make thumbnails
if ($guid && $file->simpletype == "image")
{
$file->icontime = time();
$thumbnail = get_resized_image_from_existing_file($file->getFilenameOnFilestore(), 60, 60, true);
if ($thumbnail)
{
$thumb = new ElggFile();
$thumb->setMimeType($_FILES['img_upload']['type']);
$thumb->setFilename($prefix."thumb".$filestorename);
$thumb->open("write");
$thumb->write($thumbnail);
$thumb->close();
$file->thumbnail = $prefix."thumb".$filestorename;
unset($thumbnail);
}
$thumbsmall = get_resized_image_from_existing_file($file->getFilenameOnFilestore(), 153, 153, true);
if ($thumbsmall)
{
$thumb->setFilename($prefix."smallthumb".$filestorename);
$thumb->open("write");
$thumb->write($thumbsmall);
$thumb->close();
$file->smallthumb = $prefix."smallthumb".$filestorename;
unset($thumbsmall);
}
$thumblarge = get_resized_image_from_existing_file($file->getFilenameOnFilestore(), 600, 600, false);
if ($thumblarge)
{
$thumb->setFilename($prefix."largethumb".$filestorename);
$thumb->open("write");
$thumb->write($thumblarge);
$thumb->close();
$file->largethumb = $prefix."largethumb".$filestorename;
unset($thumblarge);
}
}
if ($guid)
{
$message = elgg_echo("gallery:status:upsuccess");
system_message($message);
forward($guid->getURL());
}
I'm making an HTML PDF template and I'm about to set the background image.
Here's my code below:
<?php
class pdfAction extends sfAction{
public function execute($request){
$id = $request->getParameter('id');
if(!$id){
return $this->forward404();
}
$testTemplate = Doctrine_Core::getTable('PrintManual')->findOneById($id);
if(!$testTemplate){
return $this->forward404();
}
$config = sfTCPDFPluginConfigHandler::loadConfig('my_config');
sfTCPDFPluginConfigHandler::includeLangFile($this->getUser()->getCulture());
$pdf = new sfTCPDF();
$pdf->SetTitle('Precena Biz - Test Template');
$pdf->SetSubject('Precena Biz - Test Template');
$pdf->setHeaderFont(Array(PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN));
$pdf->setFooterFont(Array(PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA));
$content = myTools::loadTemplate('pdfTpl',array('test'=>$testTemplate), sfConfig::get('sf_root_dir') . '/apps/AdmSys/modules/test/templates');
$pdf->AddPage();
$pdf->SetFont('kochiminchosubst', "", 13);
$pdf->writeHTML($content, true, 0);
//$pdf->AddI();
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
$pdf->Output('test.pdf', 'I');
throw new sfStopException();
return $this->renderText('');
}
}
How will I add or set the image into background ?
I would suggest to use wkhtmltopdf
tool. https://code.google.com/p/wkhtmltopdf/
I'm using the tcpdf library to generate the pdf document. I'm using smarty template engine to hold the data. Below is the script to put in the header data:
// set default header data
$pdf->SetHeaderData(PDF_HEADER_LOGO, PDF_HEADER_LOGO_WIDTH, 'PQR',
'XYZ');
I want to put HTML table content of smarty template in place of XYZ, the table content is going to be dynamic(meaning the data in table may vary for each PDF document).
As #vinzcoco says, you must extend TCPDF to achieve what you want. Here is a simple improvement that I think it could be useful for you:
class MyTCPDF extends TCPDF {
var $htmlHeader;
public function setHtmlHeader($htmlHeader) {
$this->htmlHeader = $htmlHeader;
}
public function Header() {
$this->writeHTMLCell(
$w = 0, $h = 0, $x = '', $y = '',
$this->htmlHeader, $border = 0, $ln = 1, $fill = 0,
$reseth = true, $align = 'top', $autopadding = true);
}
}
Now, once you've got your MyTCPDF object available, you just need to do this to set the HTML header content:
$mytcpdfObject->setHtmlHeader('<table>...</table>');
and the HTML content won't be hardcoded into the Header() method (more flexible for you).
I used the following method to set header
$PDF_HEADER_LOGO = "logo.png";//any image file. check correct path.
$PDF_HEADER_LOGO_WIDTH = "20";
$PDF_HEADER_TITLE = "This is my Title";
$PDF_HEADER_STRING = "Tel 1234567896 Fax 987654321\n"
. "E abc#gmail.com\n"
. "www.abc.com";
$pdf->SetHeaderData($PDF_HEADER_LOGO, $PDF_HEADER_LOGO_WIDTH, $PDF_HEADER_TITLE, $PDF_HEADER_STRING);
This is work for me.
You must instance your PDF class and extend the TCPDF class.
After your PDF class should look like this:
class MyTCPDF extends TCPDF{
public function Header(){
$html = '<table>...</table>';
$this->writeHTMLCell($w = 0, $h = 0, $x = '', $y = '', $html, $border = 0, $ln = 1, $fill = 0, $reseth = true, $align = 'top', $autopadding = true);
}
}
You must adapt this to your own project.