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
- How to Upload file to S3 using Laravel Filesystem
- Upload Files to Amazon S3 using AWS PHP SDK
- Upload Files to Google Cloud Storage using PHP
If you liked this article, then please subscribe to our YouTube Channel for video tutorials.
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”,
},
Same here, after updated to Laravel 10. Have you found a solution for that error?
Nice Tutorial its working liking a charm,
very help full thank you so much