Upload Images to another Server through FTP in Laravel

Do you want to upload files from the Laravel application to another server through FTP? Laravel comes with built-in support for uploading files to an external server or cloud.

It may be possible you want to use an external server for serving static files. The obvious reason can be serving images to your application from an outside server. There are a few benefits of using this approach:

  • Saves Bandwidth: Image will be on another server that saves disk space.
  • Improves Server Performance: For images, the browser gives a call to another server. It reduces the load of the main server that results in better performance.
  • CDN like behavior: This technique is like CDN where static files are served from another server.

In order to achieve this approach, Laravel Filesystem provides a convenient way to manage your files on the cloud or external server. Using Filesystem, one can choose different storage providers like S3, Rackspace, FTP, or SFTP for their file management.

In this tutorial, I show you how to upload files(images) to another server through FTP in Laravel. If you want to use Amazon S3 for your files, check out our tutorial Upload file to S3 using Laravel Filesystem.

Getting Started

The File Transfer Protocol(FTP) is a communication protocol to transfer files from the server to a client on a computer network. This connection between computers is established through the FTP credentials. We also need FTP credentials for our tutorial. Under the hood, Laravel uses these credentials and manages your files on the external server.

Grab your FTP credentials and add them to the .env file as follows.

FTP_HOST=YOUR_FTP_HOST_VALUE
FTP_USERNAME=YOUR_FTP_USERNAME_VALUE
FTP_PASSWORD=YOUR_FTP_PASSWORD_VALUE

At the end of the tutorial, it may happen you are facing the error of connection failure. If it does, wrap your FTP credentials in the quote.

FTP_HOST="YOUR_FTP_HOST_VALUE"
FTP_USERNAME="YOUR_FTP_USERNAME_VALUE"
FTP_PASSWORD="YOUR_FTP_PASSWORD_VALUE"

Make sure you have set the document root to the public folder. Your .env file must not be accessible from an external source.

Laravel Filesystem provides drivers for a local filesystem, Amazon S3, FTP, etc. As we are dealing with FTP, we need to add the FTP driver explicitly. For this, add the ftp element along with a few configurations to the existing disks array in the config/filesystems.php.

<?php
return [
    ......
    'disks' => [
        ......
        'ftp' => [
            'driver' => 'ftp',
            'host' => env('FTP_HOST'),
            'username' => env('FTP_USERNAME'),
            'password' => env('FTP_PASSWORD'),
            'root' => 'DIR_PATH_TO_WHERE_FILE_STORE' // for example: /public_html/images
        ],
    ],
     
];

Replace DIR_PATH_TO_WHERE_FILE_STORE with the actual path where you need to store files. For example, if you have the ‘images’ folder and the path to this folder is /public_html/images then this path will go as the value for ‘root’. The other values your application will get from the environment file.

Upload Files to another Server through FTP Driver

To upload the images on the server, of course, you will have file input. I am also creating the HTML form with file input and a submit button. In my case, I called the view as image.blade.php and added the below code to it. To the file input, I keep the name as ‘profile_image’. You can adjust this name at your end.

@if ($message = Session::get('success'))
    <div class="success">
        <strong>{{ $message }}</strong>
    </div>
@endif

<form action="{{ url('store') }}" method="post" enctype="multipart/form-data">
    <p>
        <input type="file" name="profile_image" />
    </p>
    <button type="submit" name="submit">Submit</button>
    @csrf
</form>

Now, we have to perform 2 actions. Call this view and upload a file on the external server. The store route would be responsible for the second action. Let’s create the ImageController and also add their routes.

php artisan make:controller ImageController
Route::get('/image', 'ImageController@index');
Route::post('/store', 'ImageController@store');

When uploading an image, it’s a good practice to keep the unique name for each uploaded file. It will avoid overwriting existing images with the same name. We will handle this in the store() method.

Laravel provides Storage facade for uploading files to the provided disk driver. In our case, we are going to use the ‘FTP’ driver.

That being said, the ImageController will have the following code.

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

class ImageController extends Controller
{
    public function index()
    {
        return view('image');
    }

    public function store(Request $request)
    {
        if($request->hasFile('profile_image')) {
         
            //get filename with extension
            $filenamewithextension = $request->file('profile_image')->getClientOriginalName();
     
            //get filename without extension
            $filename = pathinfo($filenamewithextension, PATHINFO_FILENAME);
     
            //get file extension
            $extension = $request->file('profile_image')->getClientOriginalExtension();
     
            //filename to store
            $filenametostore = $filename.'_'.uniqid().'.'.$extension;
     
            //Upload File to external server
            Storage::disk('ftp')->put($filenametostore, fopen($request->file('profile_image'), 'r+'));
     
            //Store $filenametostore in the database
        }

        return redirect('image')->with('success', "Image uploaded successfully.");
    }
}

Head over to the browser, and test the flow. Your images should be uploaded to the external server. You should also store the name of a file in the database for later use. I have added the comment where you can write a code for storing this file name.

Retrieve or Delete the Image

If you are dealing with the images, you need to display them on the website. As we are storing these images on the known external server, you know the HTTP path where we store the images. It can be something like YOUR_DOMAIN_URL/images/. As a good practice, you can create an environment variable for your external server URL.

EXTERNAL_SERVER_URL=PASTE_YOUR_DOMAIN_URL

You can then use the HTML img tag to display the image.

<img src="{{ env('EXTERNAL_SERVER_URL') }}/images/FILE_NAME" />

Here FILE_NAME is the image name stored in the database. The Storage facade also allows the deletion of these files. You can do it using the code below.

Storage::disk('ftp')->delete('FILE_NAME');

Manage Files with SFTP Driver in Laravel

We have covered file handling using the FTP driver in Laravel. You might be using SFTP protocol for your outside server.

If you want to use SFTP instead of FTP, you don’t need to change a lot in the code written above. All you need to do is tweak some configurations.

At first, install the package for SFTP using the command:

composer require league/flysystem-sftp "~1.0"

Next, in the config/filesystems.php, to the disks array, add the SFTP configurations as follows.

'sftp' => [
    'driver' => 'sftp',
    'host' => 'example.com',
    'username' => 'your-username',
    'password' => 'your-password',
    'root' => 'DIR_PATH_TO_WHERE_FILE_STORE' // for example: /public_html/images

    // Settings for SSH key based authentication...
    'privateKey' => '/path/to/privateKey',
    'password' => 'encryption-password',

    // Optional SFTP Settings...
    // 'port' => 22,
    // 'timeout' => 30,
],

Here, I have given all available configurations for your understanding. You don’t need all of them. For instance, if you are not using SSH key-based authentication, remove their key=>value pairs. You can also remove those optional SFTP settings if not required.

I’d recommend adding credentials as the environment variables and using them just like we did for FTP configurations.

Finally, in the ImageController, to the Storage facade pass the values as ‘sftp’.

Storage::disk('sftp')->put($filenametostore, fopen($request->file('profile_image'), 'r+'));

I hope you understand how to upload files on an external server using FTP/SFTP in Laravel. Please share your thoughts and suggestions in the comment section below.

Related Articles

If you liked this article, then please subscribe to our YouTube Channel for video tutorials.

1 thought on “Upload Images to another Server through FTP in Laravel

Leave a Reply

Your email address will not be published.