How can I save file from external url Laravel public directory

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

How Can I Save Files from External URLs into the Laravel Public Directory?

As a senior developer working with frameworks like Laravel, we frequently encounter scenarios where we need to ingest external content—like images, videos, or documents from an external URL—and make that content accessible within our application. The challenge often lies not just in downloading the data, but in correctly placing and configuring the file system operations so that it is publicly accessible via the web.

You mentioned trying to use Storage::put() but ending up saving the file in the storage folder instead of the desired public directory. This is a very common point of confusion, stemming from how Laravel manages its default storage disks. Let’s break down why this happens and detail the correct, robust way to achieve your goal.

Understanding Laravel Storage Disks

Laravel's Storage facade abstracts file operations by allowing you to define "disks." By default, Laravel configures the local disk (which is what Storage::put() often defaults to) to point to the storage/app/ directory. This separation is intentional: the storage directory is intended for private application data, logs, and uploads that are not meant to be directly served by the web server.

If you want a file to be accessible via a URL (i.e., served publicly), it must reside within the public directory. Trying to use standard storage methods on this directory can lead to permission issues or incorrect routing if your web server isn't explicitly configured for that path.

The Correct Approach: Downloading and Storing Publicly

To successfully download an external file and place it into the Laravel public folder, you need a multi-step process: fetching the raw content and then manually writing that content to the public file system location. This bypasses the default configuration of the Storage facade for this specific operation.

Step 1: Fetching the External Content

First, you need an HTTP client to download the file content. The standard Laravel way is often leveraging Guzzle, which is easily accessible within your framework context.

php
use Illuminate\Support\Facades\Http;

$externalUrl = 'https://example.com/path/to/your/image.jpg';

try {
    // Fetch the raw binary content of the file
    $response = Http::get($externalUrl);

    if ($response->successful()) {
        $fileContents = $response->body();
    } else {
        throw new \Exception("Failed to download file. Status: " . $response->status());
    }
} catch (\Exception $e) {
    // Handle error appropriately
    return response()->json(['error' => 'Download failed'], 500);
}

Step 2: Saving the Content to the Public Directory

Once you have the raw binary data ($fileContents), you must use standard PHP file functions (like file_put_contents) or Laravel’s Illuminate\Support\Facades\File facade to write this content directly into your public folder.

Crucially, you need to define a path within the public directory where the file will live. For example, if you want the file accessible at /images/external/my_image.jpg, you must ensure the directory structure exists first.

php
use Illuminate\Support\Facades\File;

$fileName = 'downloaded_image.jpg';
$publicDirectory = public_path('images/external'); // Define the target path

// Ensure the directory exists before writing the file
if (!File::exists($publicDirectory)) {
    File::makeDirectory($publicDirectory);
}

$filePath = $publicDirectory . '/' . $fileName;

// Write the downloaded content to the public folder
if (File::put($filePath, $fileContents)) {
    // File successfully saved in public/images/external/downloaded_image.jpg
    return response()->json(['message' => 'File saved successfully!']);
} else {
    throw new \Exception("Failed to write file to disk.");
}

Best Practices for External File Handling

When dealing with external media, keep the following best practices in mind:

  1. Error Handling: Always wrap HTTP requests and file operations in try-catch blocks. Network failures or permission issues are common when fetching external resources.
  2. Sanitization: Never trust external data implicitly. If you are saving user-provided files, ensure you validate the MIME type and sanitize the filename before writing it to