mpdf - images from a url won't load in generated pdf - php

I'm trying to load images from a http url but they won't display in my generated pdf.
$this->layout = '//layouts/pdftemplate';
$pdf = Yii::app()->toPDF->mpdf();
$pdf->shrink_tables_to_fit = 1;
$pdf->defaultfooterline = false;
$stylesheet = file_get_contents(Yii::app()->basePath.'/../webroot/admin/themes/admin/css/formbuilder-print.css');
$pdf->WriteHTML($stylesheet, 1);
$pdf->WriteHTML($_POST['html_string']);
$pdf->Output(sys_get_temp_dir()."/test.pdf", 'F');
I'm passing the html to the php function in an ajax call. The images are on Amazon CloudFront.
Update
Thanks to Asped and Latheesan Kanes I got the issue resolved. I also used PHP's DOMDocument class to replace the image urls with the local copy of the image. This is for future reference if anyone also runs into a similar issue
$doc = new DOMDocument();
#$doc->loadHTML($_POST['html_string']);
$imgs = $doc->getElementsByTagname('img');
foreach ($imgs as $img){
$src = $img->getAttribute('src');
$name = explode('?', basename($src));
$name = $name[0];
$tmp = sys_get_temp_dir().'/'.$name;
copy($src, $tmp);
$img->setAttribute('src', $tmp);
}
$html = $doc->saveHTML(); // you can write this to the pdf. $pdf->WriteHTML($html);

I had a similar issue once displaying an SVG file in the pdf.. it would not work. Then I converted it to a PNG (on the fly), stored locally in a temp folder, and passed the temporary file to mDPF, which helped.
UPDATE - Actually now I remember I didn't even had to convert it, I just had to store it locally in a temp folder..

Related

Prevent uploading file before form submit in richtext editors?

I am trying to prevent from uploading image before form submit using summernote editor.
The code I was using (jquery/ajax) worked well for uploading image, but it was uploading image instantly when I add it to editor.
This was not desired behavior for me, 'couse if user add image to editor and then decide to close tab/close browser or go to another address, image will be stored on server - so I would like to upload image only when submit button is clicked (until then, it should be there only as preview).
I use following code which is parsing base64 coded image from editor, decoding and uploading to server.
it works fine when adding new article or updating article without adding new image into it.
Example : if article has 2 old images allready, and I add 1 more image then its trying to reupload that old images again, but old images are decoded so it doesn't upload them and inserting an undefined link into the editor.
I tried to validate with the server using :
if(file_exists($filename)){
echo 'Already exist';
}
But had no luck to make it work.
Here is my code :
if(strpos($submitted_content, '<img') !== false && strpos($submitted_content, ';base64') !== false) {
$doc = new DOMDocument();
$doc->loadHTML($submitted_content);
$tags = $doc->getElementsByTagName('img');
foreach($tags as $tag) {
// Get base64 encoded string
$srcStr = $tag->getAttribute('src');
$base64EncData = substr($srcStr, ($pos = strpos($srcStr, 'base64,')) !== false ? $pos + 7 : 0);
$base64EncData = substr($base64EncData, 0, -1);
// Get an image file
$img = base64_decode($base64EncData);
// Get file type
$dataInfo = explode(";", $srcStr)[0];
$fileExt = str_replace('data:image/', '', $dataInfo);
// Create a new filename for the image
$newImageName = str_replace(".", "", uniqid("img_", true));
$filename = $newImageName . '.' . $fileExt;
$file = '../uploads/large/' . $filename;
// Save the image to disk
$success = file_put_contents($file, $img);
$imgUrl = 'http://localhost/haber/uploads/large/' . $filename;
// Update the forum thread text with an img tag for the new image
$newImgTag = '<img src="' . $imgUrl . '" />';
$tag->setAttribute('src', $imgUrl);
$tag->setAttribute('data-original-filename', $tag->getAttribute('data-filename'));
$tag->removeAttribute('data-filename');
$submitted_text = $doc->saveHTML(); //This is the result of the editor to add database
}
Any help will be appricated! Thanks.
Solution :
I just needed to add if statement under foreach and take $submitted_text = $doc->saveHTML(); out of foreach, it works like a charm now.
if(preg_match('/data:image/', $srcStr)){}
if you want to add images to database, you can collect $filename to array $arr = array(); and implode or foreach in to database.
Can be used for all editors.

How to check if URL is blob or a link in php

How to check if a image src have a blob URL or simple URL in php
Edit
You can simply say that how to check if a object in img src is blob or not?
You can do it before using it in the image source.
Firstly take out the link from the line SRC using regex or using DomDocument like following:
$html = '';
$doc = new DOMDocument();
$doc->loadHTML($html);
$xpath = new DOMXPath($doc);
$src = $xpath->evaluate("string(//img/#src)");
Then use parse_html to check if there is host and path in the url. If the parse_html results in false then the link could be stored and check for proper files using file_put_content .
You can use file_exists to check if it is a file.
if( file_exists( $url ) ) ){
// it is a file
}
else{
// it is a blob
}

PHP: creating .docx document using .xml

I'm working on a project where I need to create a .docx document. I was using PHPWord, loading a template and then saving the file. This document has a lot of nested tables and PHPWord is breaking the tables after some replaces in the template.
So I decided to save the document as Word XML document (.xml) and do the replaces myself. I will load the text into a variable, do the replaces and then save as a new word document. My problem is that I don't know how to create a .docx document using a .xml.
Would you have some code snippets I could use?
Thanks for any help
I have come to the piece of code below. It saves the file but when I try to open using word it gives me invalid document
$xmlString = simplexml_load_file($this->config->application->fileTemplateFolder.'coi.xml')->asXML();
$xmlString = str_replace('${coi_number}', $coi['application_number'], $xmlString);
$path = $this->config->application->fileTemplateFolder.'test.docx';
$zip = new ZipArchive();
$zip->open($path, ZipArchive::CREATE);
$zip->addFromString("word/document.xml", $xmlString);
$zip->close();
Here is how I solved the issue:
private function CreateWordDocument($xmlString) {
$templateFolder = $this->config->fileTemplateFolder;
if(!endsWith($templateFolder, '/'))
$templateFolder = $templateFolder.'/';
$temp_file = tempnam(sys_get_temp_dir(), 'coi_').'.docx';
copy($templateFolder. 'coi.docx', $temp_file);
$zip = new ZipArchive();
if($zip->open($temp_file)===TRUE) {
$zip->deleteName('word/document.xml');
$zip->addFromString("word/document.xml", $xmlString);
$zip->close();
return $temp_file;
}
else {
return null;
}
}

php pdfparser is not working for pdf version 1.7

I'm using pdfparser to parse text from a pdf file. for old version pdf files it is working but for new version pdf files this parser is not working.
my pdf version is 1.7
<?php
include 'vendor/autoload.php';
// Parse pdf file and build necessary objects.
$parser = new Smalot\PdfParser\Parser();
$pdf = $parser->parseFile('sample.pdf');
// Retrieve all pages from the pdf file.
$pages = $pdf->getPages();
// Loop over each page to extract text.
$content=array();
foreach ($pages as $page) {
$content[]= $page->getTextArray();
echo"<pre>";
print_r($content);
}
I experienced the same behaviour!
Now I use a tool to check the pdf version before I try to parse it. If it is not 1.4 I convert it to 1.4 and parse it then.
Here is a php library for that if needed: https://github.com/xthiago/pdf-version-converter
Code example:
function searchablePdfParser($systemPath) {
//we save the file to a temporay file because we might need to convert it.
$tempPath = getPathWithIdAndTimestamp($systemPath) . 'tmp.pdf';
copy($systemPath, $tempPath);
//check whether it needs to be converted and convert it if required
$guesser = new RegexGuesser();
$pdfVersion = $guesser->guess($tempPath); // will print something like '1.4'
if ( $pdfVersion != '1.4' ) {
$command = new GhostscriptConverterCommand();
$filesystem = new Filesystem();
$converter = new GhostscriptConverter($command, $filesystem);
$converter->convert($tempPath, '1.4');
}
//parse the original file or the converted file if it hadn't been a pdf 1.4 version
$parser = new \Smalot\PdfParser\Parser();
$pdf = $parser->parseFile($tempPath);
$text = $pdf->getText();
unlink($tempPath);
if ( strlen($text) < 30 ) {
return '';
}
return $text;
}

php getID3 returning the same info of an updated file?

I'm using the getID3 library to get the details of a remote video file. I'm trying to read a portion of the file to get the details of the file, however some videos don't have the full details at the start.
For these videos, I'm trying to download the full video, and then extract the relevant information. However, even after the video has downloaded completely, getID3->analyze($filename), returns the same erroneous file info.
But when I copy the video, and then run the function analyze($filename.'copied.mp4') on copied video, it returns the correct info even though the file contents are same. Perhaps getID3 isn't loading the video again, however, how can I fix this issue without copying the video.
Please find the code below.
if ($fp_remote = fopen($remotefilename, 'r')) {
echo 'conn opened';
$localtempfilename = tempnam('/home/xerox/abc', 'whateva').'.mp4';
if ($fp_local = fopen($localtempfilename, 'wb')) {
$count = 0;
$countExpiry = 8;
while ($buffer = fread($fp_remote, 8192)) {
$count++;
fwrite($fp_local, $buffer);
if ($count >= $countExpiry) {
fflush($fp_local);
$getID3 = new getID3;
$ThisFileInfo = $getID3->analyze($localtempfilename);
if ($ThisFileInfo["error"]){
print "problem encouterd";
$countExpiry += 1000;
} else {
break;}
}
}
fclose($fp_local);
$getID31 = new getID3;
copy ( $localtempfilename, $localtempfilename.'_copied.mp4' );
$ThisFileInfoz = $getID31->analyze($localtempfilename.'_copied.mp4');
// Delete temporary file
unlink($localtempfilename);
fclose($fp_remote);
var_dump($ThisFileInfoz);
}
}
A call to clearstatcache solved the problem for me,
since repeated calls to things like filesize will be cached by the
filesystem and getID3 won't read beyond end-of-file.
source: James Heinrich, developer of getID3.

Categories