Files
MediaCollectorLibary/app/Utils/ImageDownloader.php
2025-10-17 13:45:57 +02:00

137 lines
4.1 KiB
PHP

<?php
namespace App\Utils;
use GuzzleHttp\Client;
use Exception;
class ImageDownloader
{
private Client $httpClient;
private string $basePath;
public function __construct(string $basePath = 'public/images', ?string $apiKey = null)
{
$headers = [
'User-Agent' => 'MediaCollector/1.0'
];
if ($apiKey) {
$headers['ApiKey'] = $apiKey;
}
$this->httpClient = new Client([
'timeout' => 30,
'headers' => $headers
]);
$this->basePath = rtrim($basePath, '/');
}
/**
* Download an image from URL and save it locally
*/
public function downloadImage(string $url, string $filename, string $subfolder = ''): ?string
{
if (empty($url) || !filter_var($url, FILTER_VALIDATE_URL)) {
error_log("Invalid URL provided: {$url}");
return null;
}
try {
$folderPath = $this->basePath;
if (!empty($subfolder)) {
$folderPath .= '/' . trim($subfolder, '/');
}
// Create folder if it doesn't exist
if (!is_dir($folderPath)) {
mkdir($folderPath, 0755, true);
}
$filePath = $folderPath . '/' . $filename;
// Check if file already exists
if (file_exists($filePath)) {
return $filePath;
}
error_log("Downloading image from: {$url} to: {$filePath}");
$response = $this->httpClient->get($url, [
'sink' => $filePath,
'headers' => [
'User-Agent' => 'MediaCollector/1.0',
'Accept' => 'image/*',
]
]);
$statusCode = $response->getStatusCode();
$contentType = $response->getHeaderLine('content-type');
error_log("Download response - Status: {$statusCode}, Content-Type: {$contentType}");
if ($statusCode === 200) {
$fileSize = filesize($filePath);
error_log("Successfully downloaded image. Size: {$fileSize} bytes");
// Check if file is actually an image and not empty
if ($fileSize > 0) {
$imageInfo = getimagesize($filePath);
if ($imageInfo !== false) {
error_log("Valid image downloaded: {$imageInfo[0]}x{$imageInfo[1]} {$imageInfo['mime']}");
return $filePath;
} else {
error_log("Downloaded file is not a valid image");
if (file_exists($filePath)) {
unlink($filePath);
}
}
} else {
error_log("Downloaded file is empty");
if (file_exists($filePath)) {
unlink($filePath);
}
}
} else {
error_log("Failed to download image. HTTP Status: {$statusCode}");
}
return null;
} catch (Exception $e) {
// Log error but don't throw - images are not critical
error_log("Failed to download image {$url}: " . $e->getMessage());
return null;
}
}
/**
* Generate a unique filename for an image
*/
public function generateFilename(string $url, string $prefix = ''): string
{
$extension = pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION);
if (empty($extension)) {
$extension = 'jpg'; // Default fallback
}
$hash = substr(md5($url . time()), 0, 8);
return ($prefix ? $prefix . '_' : '') . $hash . '.' . $extension;
}
/**
* Get the public URL for a local image
*/
public function getPublicUrl(string $localPath): ?string
{
if (empty($localPath) || !file_exists($localPath)) {
return null;
}
// Remove the public/ prefix to get the web-accessible path
$relativePath = str_replace($this->basePath . '/', '', $localPath);
return '/' . $relativePath;
}
}