Skip to content

Instantly share code, notes, and snippets.

@NazemMahmud
Last active June 11, 2025 19:12
Show Gist options
  • Save NazemMahmud/32b6278e421c545ca02119fa1915f8c3 to your computer and use it in GitHub Desktop.
Save NazemMahmud/32b6278e421c545ca02119fa1915f8c3 to your computer and use it in GitHub Desktop.
downloading images from URLs and uploading them to your storage. It Includes proper error handling, validation, and cleanup.
<?php
namespace App\Services; // this will be the namespace according to your file path
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Exception;
class ImageMigrationService
{
private int $timeout = 30; // Set your own timeout value
public function downloadAndUploadImage(string $imageUrl, string $uploadPath = 'images'): array
{
$tempPath = null;
try {
// Step 1: Download the image
$imageResponse = Http::timeout($this->timeout)->get($imageUrl);
if (!$imageResponse->successful()) {
throw new Exception("Failed to download image from URL: {$imageUrl}");
}
$imageContent = $imageResponse->body();
if (empty($imageContent)) {
throw new Exception("Downloaded image content is empty");
}
// Step 2: Create temporary file
$originalFilename = $this->extractFilenameFromUrl($imageUrl);
$tempPath = rtrim(sys_get_temp_dir(), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . uniqid('img_') . '_' . $originalFilename;
if (file_put_contents($tempPath, $imageContent) === false) {
throw new Exception("Failed to write image to temporary file");
}
// Step 3: Validate the file is actually an image
$mimeType = mime_content_type($tempPath);
if (!$mimeType || !str_starts_with($mimeType, 'image/')) {
throw new Exception('Downloaded file is not a valid image (MIME: ' . $mimeType . ')');
}
// Step 4: Create UploadedFile instance
$uploadedFile = new UploadedFile(
$tempPath,
$originalFilename,
$mimeType,
null,
true
);
// Step 5: Upload to your storage (customize this part according to your project requirement)
$uploadResult = $this->uploadToStorage($uploadedFile, $uploadPath);
return $uploadResult;
} catch (Exception $ex) {
if ($tempPath && file_exists($tempPath)) {
unlink($tempPath);
}
throw $ex;
}
}
/**
* this is a sample example, your upload code might be different based on your requirements
* such as, you might want to upload in aws s3 storage, so upload method would be different for you
*/
private function uploadToStorage(UploadedFile $file, string $path): array
{
try {
// Example using Laravel's storage facade
$filename = time() . '_' . $file->getClientOriginalName();
$storedPath = $file->storeAs($path, $filename, 'public');
return [
'success' => true,
'path' => $storedPath,
'url' => asset('storage/' . $storedPath),
'filename' => $filename
];
} finally {
// Step 6: Always clean up temporary file,
// don't use finally inside download method above
// because, at that time temporary file will get deleted before file upload and you will get error
if ($tempPath && file_exists($tempPath)) {
unlink($tempPath);
}
}
}
private function extractFilenameFromUrl(string $url): string
{
$filename = basename(parse_url($url, PHP_URL_PATH));
if (empty($filename) || !pathinfo($filename, PATHINFO_EXTENSION)) {
$filename = 'image_' . time() . '_' . uniqid() . '.jpg';
}
// Sanitize filename
return preg_replace('/[^a-zA-Z0-9._-]/', '_', $filename);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment