I've asked this question but it resulted to be a duplicate question and the answers given did not help my case. Please note that I'm new to php and got this code from here (https://hackthestuff.com/article/download-images-from-any-website-using-php) however I did some changes on index.php.
I'm pretty sure the solution to my case is simple but none of the solution on the internet fits my case. I am using PHP to download image from multiple website at once and store into my local server.
I have an excel Book1.csv
that contains all the product number in column A
. (123
, 456
,...)
But here's the thing, the file name could be better and I was thinking of changing the file name to the product number. For example I have a product number in row 1 (123)
, when I download images for this product, the image file name should be 123.jpg
.
How do I rewrite the file name when downloading the images instead of renaming it individually?
ImageDownload.php:
<?php
class ImageDownload
{
/**
* file directory path
*
* @return void
*/
public $folder = 'images';
/**
* website link
*
* @return void
*/
public $websitelink;
/**
* Create a new class instance.
*
* @return void
*/
function __construct($websitelink)
{
if (!file_exists($this->folder)) {
mkdir($this->folder, 0777, true);
}
$this->websitelink = $websitelink;
}
/**
* save file.
*
* @return void
*/
public function getLinks()
{
$html = file_get_contents($this->websitelink);
preg_match_all("{<img\\s*(.*?)src=('.*?'|\".*?\"|[^\\s] )(.*?)\\s*/?>}ims", $html, $image_urls, PREG_SET_ORDER);
return $image_urls;
}
/**
* save file.
*
* @return void
*/
public function saveImage($images)
{
foreach ($images as $val) {
$pos = strpos($val[2],"/");
$link = substr($val[2],1,-1);
if($pos == 1) {
$site = parse_url($this->$websitelink);
$image_url = $site['scheme'].'://'.$site['host'].$link;
} else {
$image_url = $link;
}
$image_name = pathinfo($image_url)['basename'];
copy($image_url, $this->folder.'/'.$image_name);
}
}
}
Index.php:
<?php
include "ImageDownload.php";
$file = fopen("Book1.csv","r");
// Remote image URL
while (($result = fgetcsv($file)) !== false)
{
$fileName = rawurlencode($result[0]).".html";
$website_link = "https://www.rockwellautomation.com/en-us/products/details.".$fileName;
$downloader = new ImageDownload($website_link);
$images = $downloader->getLinks();
$downloader->saveImage($images);
}
Here's what I've tried in index.php
:
header('Content-Disposition: attachment; filename="'.$fileName.'"');
Error Message shown:
Notice: Undefined variable: filename in C:\index.php on line 2
Please help, thank you!
CodePudding user response:
Break your problem up into small parts, and work on each one in turn.
First, you want the product ID - but you already have that, that's what $fileName
is, right?
OK, so moving along, where do you want to use that variable? In the code that names the file. Where is that? Has to be in saveImage()
, right, specifically the copy()
line?
copy($image_url, $this->folder.'/'.$image_name);
If you're not sure how that line works, let's check the docs. Seems pretty simple - there a from
filename and a to
filename. You want to use your product ID as the to
filename, right? So let's try:
copy($image_url, $this->folder . '/' . $fileName);
We're making progress! But if you run that, you'll get an error, something like:
Undefined variable $fileName
If you look at the code, you'll see that the other variable used inside that function ($images
) is passed in as a parameter:
$downloader->saveImage($images);
and in the function definition:
public function saveImage($images) {
So, probably we need to pass other variables in in the same way? Let's try. Update the line calling the function to use the $fileName
as well:
$downloader->saveImage($images, $fileName);
And update the function definition to expect the new variable:
public function saveImage($images, $fileName) {
Now try running, how does it go? Whoops - $fileName
doesn't include an extension! OK, but you're already extracting info about the image filename from the URL using pathinfo()
, maybe it can help with extensions? Let's check the docs - bingo, it is just as easy as getting the filename:
$extension = pathinfo($image_url)['extension'];
So you need that in your copy()
line too:
copy($image_url, $this->folder . '/' . $fileName . '.' . $extension);
Try running it again. You'll notice 1 final problem - there are multiple images per page, they can't all have the same target filename (or rather they can, but each one will just overwrite the last one). So, how to solve that? How about add a number, which increments each time? How would you do that? A simple search for "php increment filename" turns up plenty of examples, here's one.
In your case, update saveImage()
to look something like this:
// Variable to track image number
$i = 0;
foreach ($images as $val) {
// Increment image number each loop
$i
// ... rest of the code
// Finally, include the number in the filename, so every name is unique
copy($image_url, $this->folder . '/' . $fileName . '-' . $i . '.' . $extension);
}