Upload Images to another Server through FTP/SFTP in Laravel

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

You may want to use the remote server for storage of static files. Some people wish to serve images into the application from an external server. There are a few benefits of using this approach:

  • Saves Bandwidth: When you stored images on a remote server, it saves disk space on the application server.
  • Improves Server Performance: For images, the browser gives a call to the remote server. It reduces the load of the main server which 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 functionality, 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 file management.

In this tutorial, I show you how to upload files(images) to another server through FTP and SFTP in Laravel. If you want to use Amazon S3 for managing 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 the FTP credentials to transfer files programmatically. Under the hood, Laravel uses these credentials and manages your files on the external server.

On the other hand, SFTP(Secure File Transfer Protocol) also allows to transfer files. The SFTP adds an extra layer of security to a connection.

Let’s first start with the FTP connection. Grab your FTP credentials and add them to the .env file as follows. While adding credentials wrap your values into the quote to avoid connection failure error.

FTP_HOST="YOUR_FTP_HOST"
FTP_USERNAME="YOUR_FTP_USERNAME"
FTP_PASSWORD="YOUR_FTP_PASSWORD"
FTP_ROOT="REMOTE_DIRECTORY_PATH"

Replace REMOTE_DIRECTORY_PATH 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 be the value for FTP_ROOT.

Make sure you have set the document root to the public folder. Your .env file must not be accessible on the Internet.

Laravel Filesystem provides drivers for a local filesystem, Amazon S3, FTP, SFTP, 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' => env('FTP_ROOT') // for example: /public_html/images

            // Optional FTP Settings...
            // 'port' => env('FTP_PORT', 21),
            // 'passive' => true,
            // 'ssl' => true,
            // 'timeout' => 30,
        ],
    ],
     
];

To use this ftp driver, you must install the Flysystem FTP package using the Composer command.

composer require league/flysystem-ftp "^3.0"

Upload Files to another Server through FTP Driver

You will require a file input to upload the images. I am creating the HTML form with file input and a submit button. In my case, I called the view as image.blade and added the below code to it. To the file input, I keep the name as ‘profile_image’. You can adjust this name on 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">
    @csrf
    <p>
        <input type="file" name="profile_image" />
    </p>
    <button type="submit" name="submit">Submit</button>
</form>

Next, 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 add the required 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 a unique name for each uploaded file. It will avoid overwriting existing images with the same name. I’ll 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 will get uploaded to the remote 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 in the database.

Retrieve or Delete the Image

If you are dealing with the images, you obviously want to display them on the website. As we are storing these files on the external server, you know the HTTP path of the images. It can be something like YOUR_DOMAIN_URL/images/. Create an environment variable for your remote server URL.

REMOTE_SERVER_URL=PASTE_YOUR_DOMAIN_URL

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

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

Here FILE_NAME is the name of the image stored in the database. The Storage facade also allows the deletion of these files. You can delete files 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 the SFTP protocol for your remote server. Let’s see now how to use the SFTP driver in Laravel.

In the case of SFTP, you don’t need to change a lot in the above code. All you need to do is tweak some configurations.

First, install the Flysystem package for SFTP using the Composer command:

composer require league/flysystem-sftp-v3 "^3.0"

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

'sftp' => [
    'driver' => 'sftp',
    'host' => env('SFTP_HOST'),
    'username' => env('SFTP_USERNAME'),
    'password' => env('SFTP_PASSWORD'),
    'root' => env('SFTP_ROOT'),
 
    // Settings for SSH key based authentication with encryption password...
    //'privateKey' => env('SFTP_PRIVATE_KEY'),
    //'passphrase' => env('SFTP_PASSPHRASE'),
 
    // Optional SFTP Settings...
    // 'hostFingerprint' => env('SFTP_HOST_FINGERPRINT'),
    // 'maxTries' => 4,
    // 'passphrase' => env('SFTP_PASSPHRASE'),
    // 'port' => env('SFTP_PORT', 22),
    // 'timeout' => 30,
    // 'useAgent' => true,
],

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.

Add your SFTP credentials to the .env file just like we did for the FTP driver.

SFTP_HOST="YOUR_SFTP_HOST"
SFTP_USERNAME="YOUR_SFTP_USERNAME"
SFTP_PASSWORD="YOUR_SFTP_PASSWORD"
SFTP_ROOT="REMOTE_DIRECTORY_PATH"

Finally, in the ImageController, to the disk function of Storage facade pass the ‘sftp’ value.

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

It should upload your images on your SFTP-configured remote server. Similarly, you can easily access and delete the images using the same code given for FTP(just pass sftp as a driver to the disk method).

I hope you understand how to upload files on an external server using FTP/SFTP in Laravel. We also studied accessing and deleting files from and on the remote server.

Related Articles

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

3 thoughts on “Upload Images to another Server through FTP/SFTP in Laravel

  1. I am getting this error .

    message: “Class “League\Flysystem\Ftp\FtpAdapter” not found”, exception: “Error”,…}
    exception: “Error”
    file:”/Applications/XAMPP/xamppfiles/htdocs/oms/vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemManager.php”
    “Class \”League\\Flysystem\\Ftp\\FtpAdapter\” not found”.

    The package is also installed but still getting error.
    ————————————————–
    composer.json file
    “require”: {
    ………… ,
    “league/flysystem-ftp”: “^3.0”,
    },

Leave a Reply

Your email address will not be published. Required fields are marked *