How to Download Files From URL In Laravel And Save them in the Storage.

Laravel download From Url

In this tutorial, Let’s create Laravel storage to save files and images from URLs after renaming them using Laravel’s file system to make them unique.

We will allow the user to create a subdirectory in the storage. In addition to, generating a URL to send to the front-end via RESTful API to download.

I’m using Laravel 10, and this works with most previous versions. Let’s create our storage.

Laravel File Storage

Let’s create a storage to save our files, I’ll name it attachments, we need to create a folder storage\app\attachments then let’s write the code for creating the storage config\filesystems.php

//
'attachments' => [
            'driver' => 'local',
            'root' => storage_path('app/attachments'),
            'url' => env('APP_URL').'/attachments',
            'visibility' => 'public',
            'throw' => false,
        ],
//
'links' => [
        public_path('storage') => storage_path('app/public'),
        public_path('attachments') => storage_path('app/attachments'),
      ],

Finally, we need to create a link to our new storage.

php artisan storage:link

Now we are ready for the next step.

Files Processing Trait

It’s better to create a trait for this type of function so we can use them wherever we want in our application. So let’s create a directory for all traits app\Traits and the trait itself app\Traits\FilesProcessing.php

<?php
namespace App\Traits;
use File;
use Storage;

trait FilesProcessing{


}

Our first function is for creating a directory, let’s say we have a user that wants to create a gallery with the name “fruits”, what we have to do here is to create a folder in our storage with the name “fruits”.

public function makeDirectory($path){
        // Check if the directory already exists.
        if (!File::isDirectory($path)) {

            // Create the directory.
            File::makeDirectory($path);
        }
    }

The File::makeDirectory() method takes one argument, the directory you want to create.

The next function is for downloading the file from the URL.

    function downloadFileFromUrl($url, $storageName, $subfolder = '') {

        //To add subdirectory to the filename
        $addSubFolder = '';

        if($subfolder){
        //Check if the directory exists
        $path =  Storage::disk( $storageName)->path($subfolder);
        $this->makeDirectory($path);
        $addSubFolder = $subfolder.'/';
        }
        // Get the current date and time.
        $dateTime = now();
    
        // Generate a unique filename.
        $filename = $addSubFolder.$dateTime->format('YmdHis') . '_' . basename($url);
        
        // Download the file from the URL.
        Storage::disk($storageName)->put( $filename, file_get_contents($url));

        // Get the file url to download
        return Storage::disk($storageName)->url($filename);
    }

This function takes three arguments:

  • The URL of the file to download.
  • The name of the storage to use.
  • The subfolder or directory to add the file in, it’s optional.

We use $addSubFolder to add a subdirectory to the filename, In addition to the date time to make the file name unique and avoid overwriting files. And finally, we download the file from the URL and return a URL to the file.

The Controller and Routes

php artisan make:controller FileController
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Traits\FilesProcessing;
use Storage;
class FileController extends Controller
{
    use FilesProcessing;

    public function download(Request $request)
    {
  
        // Get the URL of the file to download.
        $url = $request->url;

        // Get the name of the storage to use.
        $storageName = $request->storageName;

        // Download the file from the URL.
        $urlToDownload = $this->downloadFileFromUrl($url, $storageName, $request->subfolder);

        // Return a success response with the file url.
        return response()->json([
            'success' => true,
            'url' => $urlToDownload,
        ]);
    }
}

We are using the downloadFileFromUrl function in the controller which is called FileController. The action takes two arguments:

  • The URL of the file to download.
  • The name of the storage to use.
  • The subdirectory is optional.

Finally, the route below in routes\api.php

Route::post('/download', [FileController::class, 'download']);

That’s all, thank you.