mirror of
https://github.com/ceratic/MediaCollectorLibary.git
synced 2026-05-14 08:06:47 +02:00
184 lines
5.5 KiB
PHP
184 lines
5.5 KiB
PHP
<?php
|
|
|
|
namespace App\Utils;
|
|
|
|
use GuzzleHttp\Client;
|
|
use Exception;
|
|
|
|
class ImageDownloader
|
|
{
|
|
private Client $httpClient;
|
|
private string $basePath;
|
|
|
|
public function __construct(string $basePath = 'storage/images', ?string $apiKey = null)
|
|
{
|
|
$headers = [
|
|
'User-Agent' => 'MediaCollector/1.0'
|
|
];
|
|
|
|
if ($apiKey) {
|
|
$headers['ApiKey'] = $apiKey;
|
|
}
|
|
|
|
$this->httpClient = new Client([
|
|
'timeout' => 30,
|
|
'headers' => $headers,
|
|
'verify' => false // Disable SSL verification for problematic servers
|
|
]);
|
|
|
|
// Convert relative path to absolute path
|
|
if (strpos($basePath, '/') !== 0) {
|
|
$this->basePath = __DIR__ . '/../' . $basePath;
|
|
} else {
|
|
$this->basePath = $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;
|
|
}
|
|
|
|
$maxRetries = 3;
|
|
$retryDelay = 2; // seconds
|
|
|
|
for ($attempt = 1; $attempt <= $maxRetries; $attempt++) {
|
|
try {
|
|
error_log("Downloading image (attempt {$attempt}/{$maxRetries}): {$url}");
|
|
|
|
$response = $this->httpClient->get($url, [
|
|
'timeout' => 60, // Longer timeout for large images
|
|
'connect_timeout' => 30,
|
|
'headers' => [
|
|
'User-Agent' => 'MediaCollector/1.0',
|
|
'Referer' => parse_url($url, PHP_URL_HOST)
|
|
]
|
|
]);
|
|
|
|
if ($response->getStatusCode() !== 200) {
|
|
error_log("HTTP {$response->getStatusCode()} for {$url}");
|
|
if ($attempt === $maxRetries) {
|
|
return null;
|
|
}
|
|
sleep($retryDelay);
|
|
continue;
|
|
}
|
|
|
|
$imageData = $response->getBody()->getContents();
|
|
if (empty($imageData)) {
|
|
error_log("Empty response for {$url}");
|
|
if ($attempt === $maxRetries) {
|
|
return null;
|
|
}
|
|
sleep($retryDelay);
|
|
continue;
|
|
}
|
|
|
|
// Validate image data
|
|
if (!$this->isValidImage($imageData)) {
|
|
error_log("Invalid image data for {$url}");
|
|
if ($attempt === $maxRetries) {
|
|
return null;
|
|
}
|
|
sleep($retryDelay);
|
|
continue;
|
|
}
|
|
|
|
return $this->saveImage($imageData, $filename, $subfolder);
|
|
|
|
} catch (Exception $e) {
|
|
error_log("Error downloading {$url} (attempt {$attempt}): " . $e->getMessage());
|
|
|
|
if ($attempt === $maxRetries) {
|
|
error_log("Failed to download {$url} after {$maxRetries} attempts");
|
|
return null;
|
|
}
|
|
|
|
sleep($retryDelay);
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private function isValidImage(string $data): bool
|
|
{
|
|
// Check for common image signatures
|
|
$imageTypes = [
|
|
'image/jpeg' => "\xFF\xD8\xFF",
|
|
'image/png' => "\x89PNG",
|
|
'image/gif' => "GIF",
|
|
'image/webp' => "RIFF"
|
|
];
|
|
|
|
foreach ($imageTypes as $type => $signature) {
|
|
if (strpos($data, $signature) === 0) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false; // Not a valid image type
|
|
}
|
|
|
|
public function saveImage(string $imageData, string $filename, string $subfolder = ''): ?string
|
|
{
|
|
try {
|
|
// Create subfolder if it doesn't exist
|
|
$fullPath = $this->basePath;
|
|
if (!empty($subfolder)) {
|
|
$fullPath .= '/' . trim($subfolder, '/');
|
|
}
|
|
|
|
if (!is_dir($fullPath)) {
|
|
mkdir($fullPath, 0755, true);
|
|
}
|
|
|
|
$filePath = $fullPath . '/' . $filename;
|
|
|
|
// Write image data to file
|
|
$bytesWritten = file_put_contents($filePath, $imageData);
|
|
if ($bytesWritten === false || $bytesWritten === 0) {
|
|
error_log("Failed to write image data to {$filePath}");
|
|
return null;
|
|
}
|
|
|
|
return $filePath;
|
|
|
|
} catch (Exception $e) {
|
|
error_log("Error saving image {$filename}: " . $e->getMessage());
|
|
return null;
|
|
}
|
|
}
|
|
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 absolute basePath prefix to get the relative path
|
|
$relativePath = str_replace($this->basePath . '/', '', $localPath);
|
|
|
|
return '/images/' . $relativePath;
|
|
}
|
|
}
|