I have a string that contains text and photos as you can see bellow.
My code so far get all the images and upload them into a folder.
I need to replace the new uploaded links with the correct oreder.
$nextstep = "Hello there this is image 1 <img src='http://www.demosite.com/wp-content/uploads/2015/01.jpg' width='653' height='340' alt='xxx' title='xxx'> !! And Now you can see image number 2 <img src='http://www.demosite.com/wp-content/uploads/2015/02.jpg' width='653' height='340' alt='xxx' title='xxx'>";
$string = $nextstep;
$doc = new DOMDocument();
$doc->loadHTML($string);
$images = $doc->getElementsByTagName('img');
foreach ($images as $image) { //STARTING LOOP
echo "</br>";
echo $image->getAttribute('src') . "\n";
echo "</br>";
$urlimg = $image->getAttribute('src'); //IMAGE URL
$URL = urldecode($urlimg);
$image_name = (stristr($URL,'?',true))?stristr($URL,'?',true):$URL;
$pos = strrpos($image_name,'/');
$image_name = substr($image_name,$pos+1);
$extension = stristr($image_name,'.');
if($extension == '.jpg' || $extension == '.png' || $extension == '.gif' || $extension == '.jpeg'){
$img = '../images/' . $image_name;
file_put_contents($img, file_get_contents($url)); //UPLOAD THEM ONE BY ONE
}
}
It's not clear what the desired outcome is here. It sounds like you want to change the src URL in your existing string to the one where you've saved the images. If this isn't the case please do try updating the question for more clarity.
Here's a simple way to break down the problem...
Step 1 - Extract the img tags from DOM using source string
$html = <<<'HTML'
Hello there this is image 1 <img src="http://www.demosite.com/wp-content/uploads/2015/01.jpg" width="653" height="340" alt="xxx" title="xxx"> !!
And Now you can see image number 2 <img src="http://www.demosite.com/wp-content/uploads/2015/02.jpg" width="653" height="340" alt="xxx" title="xxx">
HTML;
$dom = new DOMDocument;
$dom->loadHTML($html);
$imgs = $dom->getElementsByTagName('img');
// Store the list of image urls in an array - this will come in handy later
$imgURLs = [];
foreach($imgs as $img) {
if (!$img->hasAttribute('src')) {
continue;
}
$imgURLs[] = $img->getAttribute('src');
}
Step 2 - Save the image in a different location
$newImgURLs = []; // new modified URLs where images were moved
$newPath = '../images'; // wherever you're saving the images
foreach($imgURLs as $imgURL) {
/**
* Use parse_url and pathinfo to break down the URL parts and extract the
* filename/extension instead of the fragile implementation you used above
*/
$URLparts = parse_url($imgURL);
$file = pathinfo($URLparts['path']);
$fileName = $file['filename'] . '.' . $file['extension'];
$newFileName = $newPath . '/' . $fileName;
$newImgURLs[] = $URLparts['scheme'] . '://' .
$URLparts['host'] . $file['dirname'] . '/' . $newFileName .
(isset($URLparts['query']) ? ('?' . $URLparts['query']) : null) .
(isset($URLparts['fragment']) ? ('#' . $URLparts['fragment']) : null);
// download image and save to new location
file_put_contents($newFileName, file_get_contents($imgURL));
}
Step 3 - Modify the img src URLs to new path
foreach($imgs as $i => $img) {
$img->setAttribute('src', $newImgURLs[$i]);
}
echo $dom->saveHTML(); // new updated DOM
// or just create a new $html string from scratch using the new URLs.
Related
Find and convert all images to base64 from html
I'm working on a screenshot project using html2canvas. My business is constrained by images that can not be rendered, so that all images from the url can not be displayed.
But I tried to replace one of the image urls with a new image that has been converted to base64, and it works.
So here I have found the solution, just can not apply to my site. I need help to compile the code in order to finish my project.
Could there be any way to change this code:
<?php
echo '
<html>
<body>
<div><img src="/image1.jpg" /></div>
<p><img src="/image2.png" /></p>
</body>
</html>
'
?>
TO
<?php
echo '
<html>
<body>
<div><img src="base64,/9j/4AAQSkZJRgABAQAAAQABAA_blablabla..." /></div>
<p><img src="base64,/9h/4AAQSkZJRgABAQAAAQABAA_blablabla..." /></p>
</body>
</html>
'
?>
I've tried with this code FROM How to convert an image to base64 encoding?
$path = 'myfolder/myimage.png';
$type = pathinfo($path, PATHINFO_EXTENSION);
$data = file_get_contents($path);
$base64 = 'data:image/' . $type . ';base64,' . base64_encode($data);
But can not apply it to all image URLs.
UPDATE===
The main topic of this question is how to convert all images to base64
I assume how it works if using jQuery like this:
<script>
$(function(){
$('img').each(function() {
$(this).attr('src', 'BASE64 GENERATED');
});
});
</script>
the best practice to follow is the DOMDocument , here's an example of how to do that .
$html = '<html>....</html>';
$dom = new DOMDocument();
$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
$images = $dom->getElementsByTagName('img');
foreach ($images as $image) {
$src = $image->getAttribute('src');
$type = pathinfo($src, PATHINFO_EXTENSION);
$data = file_get_contents($src);
$base64 = 'data:image/' . $type . ';base64,' . base64_encode($data);
$image->setAttribute("src", $base64);
}
$html = $dom->saveHTML();
I am trying to understand why GLOB is skipping the first image in whatever folder I direct it too. I work around it by placing a dummy image named so it is listed first but I would like to solve this irk in a more efficient way. Here is my code.
<?php
// This retrieves images from a selected folder - anchor with a data-xx-xx attribute
// via jQuery - click - the data-xx-x value is put into a hidden field : foldpath
// It all works fine BUT, it always fails to return the first image in a folder
// I get around it by placing within each folder a dummy image called aa.jpg
// which hopefully will always be the first image but it is not really a
// satisfactory solution.
if($_POST && isset($_POST["foldsub"]) && isset($_POST["foldpath"]) ){
// hidden field $_POST["foldpath"];
//A typical path might be :
// ../images/products/CLIENTS_images/bridal_whatnots/bridal_belts
//the ../ prefix is reoved via php when the page is displayed and replaced by DIR
// for testing between admin folders and the main root folders I use the relative paths.
$fp = $_POST["foldpath"];
$files = glob($fp ."/" ."*.*");
//this is a pop up page which needs to stay open after the selection has been made
echo "<script> $(\"#imgstuff\").css({\"display\":\"block\"});</script>";
//the form closed on whgen the close x is selected
}else
{
//default
$files = glob("../images/bannerImgs/*.*");
}
for ($i=0; $i<count($files); $i++)
{
$image = $files[$i];
$supported_file = array(
'jpg',
'jpeg',
'png'
);
$ext = strtolower(pathinfo($image, PATHINFO_EXTENSION));
if (in_array($ext, $supported_file)) {
// print $image ."<br />";
$path = $image;
$path1 = DIR;
if (strpos($path, $path1) !== false) {
$path2 = $path;
}else{
$path2 = str_replace('../', '', $path);
$path2 = $path1.$path2;
}
$fn = basename($path);
$fn = basename($path, PATHINFO_EXTENSION);
if($fn!="aa.jpg"){
echo '<p class="imgdet">';
// echo '<span class="imglongpath">' . $path2 .'</span>';
echo '<img src="'.$image .'" alt="Random image" />';
echo '<span class="imgname">' . $fn .'</span>';
// echo '<span class="imgmesg">Now click Confirm / Set Choice</span>';
// "<br /><br />";
echo "</p>";
}
} else {
continue;
}
}
?>
I have a directory with almost 60 images but in HD quality so theirs size are around 5 ~ 6 MB and load all them in a web page is to much time for server and browser so both hang up. I read this post and this other too and since I'm using PHP 5.4.20 in my server I'll like to use DirectoryIterator and LimitIterator but example leave in the post are not so explicit to me since I don't know how to move forward/backward in this cases. Can any give me some sample code about paginate files in a directory?
UPDATE: show some code
Right now this is how I read files:
function directoryToArray($directory, $recursive) {
$array_items = array();
if ($handle = opendir($directory)) {
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != "..") {
if (is_dir($directory . "/" . $file)) {
if ($recursive) {
$array_items = array_merge($array_items, directoryToArray($directory . "/" . $file, $recursive));
}
$file = $directory . "/" . $file;
$array_items[] = preg_replace("/\/\//si", "/", $file);
} else {
$file = $directory . "/" . $file;
$array_items[] = preg_replace("/\/\//si", "/", $file);
}
}
}
closedir($handle);
}
return $array_items;
}
$images = directoryToArray("images/portfolio/");
for ($i = 0; $i < count($images); $i++) {
$old_img_name = explode('/', $images[$i]);
$new_img_name = $old_img_name[0] . "/" . $old_img_name[1] . '/large/' . $old_img_name[2];
echo '<div class="span4 element">';
echo '<div class="hover_img">';
echo '<img src="' . $images[$i] . '" alt="" />';
echo '<span class="portfolio_zoom"></span>';
echo '</div>';
echo '</div>';
}
Aristona's absolutely right. You should probably resize the images to an appropriate file-format, quality & size. At the very least if you're trying to make some sort of gallery, you could use something like image magick to make 'thumbnails' for the gallery where clicking on them may take you to the full-quality image.
Image magick is scriptable in a variety of languages to batch process your images and build thumbnails if you want it to run as a process, alternatively from the command line you can do it as a once off, something like what's mentioned here:
Batch resize images into new folder using ImageMagick
I'm trying to extract images from a web page.
I am using the follolwing code but it gives no output although i know there is some there (used ebay page as example)
$html = "http://www.ebay.co.uk/itm/190706137456?_trkparms=clkid%3D1088812801530482649&_qi=RTM944765";
$dom = new domDocument;
#$dom->loadHTML($html);
$dom->preserveWhiteSpace = false;
$images = $dom->getElementsByTagName('img');
foreach ($images as $image) {
echo $image->getAttribute('src');
}
Further to this is it possible to just extract jpg images, and then further, only images above a certain height/width size?
I've been using simple_html_dom recently but it fails a lot of the time and I find it slow.
Is there a way, for example, instead of looking for 'img' and 'src' to just find anything that ends '.jpg' the strip everything before 'http://...etc etc..'
Try using $dom->loadHTMLFile() instead of $dom->loadHTML. So...
$html = "http://www.ebay.co.uk/itm/190706137456?_trkparms=clkid%3D1088812801530482649&_qi=RTM944765";
$dom = new domDocument();
$dom->loadHTMLFile($html);
You can filter image types (and get only the file name) in your foreach() loop. Try something like this:
$images = $dom->getElementsByTagName('img');
foreach ($images as $image) {
$filename = basename($image->getAttribute('src'));
$ext = pathinfo($filename, PATHINFO_EXTENSION);
if ($ext == 'jpg') {
echo $filename . '<br>';
}
}
You can also filter by image width and height, but it appears to be weird with how it finds the width and height. You'd imagine that by using these attributes...
$width = $image->getAttribute('width');
$height = $image->getAttribute('height');
...It would spit out the width="xxx" and height="yyy"...but it doesn't. It looks like it takes the style attributes instead. So keep that in mind. That being said, you can use a similar solution like above for width and height too. Like so:
$images = $dom->getElementsByTagName('img');
foreach ($images as $image) {
$filename = basename($image->getAttribute('src'));
$width = $image->getAttribute('width');
$height = $image->getAttribute('height');
$ext = pathinfo($filename, PATHINFO_EXTENSION);
if ($ext == 'jpg' && ($width > 20 && $height > 10)) {
echo $filename . "($width x $height)" . '<br>';
}
}
Hopefully that works for you. Here's everything, in case you need it:
$html = "http://www.ebay.co.uk/itm/190706137456?_trkparms=clkid%3D1088812801530482649&_qi=RTM944765";
$dom = new domDocument();
$dom->loadHTMLFile($html);
$dom->preserveWhiteSpace = false;
$images = $dom->getElementsByTagName('img');
foreach ($images as $image) {
$filename = basename($image->getAttribute('src'));
$width = $image->getAttribute('width');
$height = $image->getAttribute('height');
$ext = pathinfo($filename, PATHINFO_EXTENSION);
if ($ext == 'jpg' && ($width > 20 && $height > 10)) {
echo $filename . "($width x $height)" . '<br>';
}
}
I am trying to get images from while loop and split them up at the period (.).. and then change the name of the image to ImageName + -resized. But I can not seem to figure out how to do this. Any help would be greatly appreciated!
So in short I have this: image.jpg and I want to create this image-resized.jpg: Here is my code:
<?php
$f = $_GET['f'];
$h = $_GET['h'];
$gp = $_GET['gp'];
//Create folder path
$path = "Fotos/".$f."/".$h."/".$gp."/";
//Get pictures from database
$getfolders = mysql_query("SELECT FolderName, Files FROM Files WHERE FolderDate = '$f' AND FolderHour = '$h' AND FolderName = '$gp'") or die(mysql_error());
//List pictures from database
while($row = mysql_fetch_array($getfolders)){
$img = $row['Files'];
//Seperate image at period(.)
$image = explode('.', $img);
//Get image name ----------------Here is where I need help!!
for($i = 0; $i < sizeof($image); $i++)
{
$imag = $image[$i];
}
?>
<div class="picture" id="pic"><img src="<?php echo $path; echo $imag ?>" alt="picture" /><?php echo $img?></div>
<?php
}
?>
Well, the simplest solution would be:
$image = explode('.', $img);
$extension = array_pop($image);
$resizedFileName = implode('.', $image) . "-resized.{$extension}";
But this solution does assume, that there are only simple extensions:
image.jpg => image-resized.jpg // ok
image.tar.gz => image.tar-resized.gz // not so ok
But if there are only simple extensions, this solution might be sufficient.
A better solution would be using SplFileInfo:
$fi = new SplFileInfo($image);
$resizedFileName = $fi->getBasename("." . $fi->getExtension()) . "-resized." . $fi->getExtension();
SplFileInfo::getExtensions() is available since PHP 5.3.6