Laravel php delete a directory (folder) via sftp

306 Views Asked by At

I am trying to delete a folder on my server via sftp. I am using php 7.4.13 and laravel 7.30.4

I have set up my sftp drive and everything (upload, delete files, create directory) works fine.

But the only problem is that I could not delete a folder.

I am using deleteDirectory($directory) function which is written on the official laravel documentation: https://laravel.com/docs/7.x/filesystem

Here is my set up: filesystem.php

'disks' => [
    'sftp' => [
        'driver' => 'sftp',
        'host' => env('SFTP_HOST'),
        'username' => env('SFTP_USERNAME'),
        'password' => env('SFTP_PASSWORD'),
        'timeout' => env('SFTP_TIMEOUT'),
        'port' => env('SFTP_PORT'),
]

Here is my code: Storage::disk('sftp')->deleteDirectory('path/to/folder')

But the folder still exists and all files inside the folder also still exist. There is no error message. And also if I dd() the code above, it returns true.

I have all permission to create, write and delete on this server. And also I can delete folder on this server using WinSCP via sftp.

Could anyone tell me which part I did wrong or what function I can use to achieve this?

Thanks a lot and I will provide more information if you need it.

TLDR: I tried: Storage::disk('sftp')->deleteDirectory('path/to/folder') but not working.

EDIT: File permission enter image description here

EDIT 2: Tried to delete all files inside the folder first then delete the folder

$files = Storage::disk('sftp')->allFiles('QCS/test_folder');
Storage::disk('sftp')->delete($files);
try { Storage::disk('sftp')->deleteDirectory('QCS/test_folder', true); } catch (\Exception $e) { dd($e->getMessage()); }

EDIT 3: Tried to remove the second parameter of deleteDirectory() function

$files = Storage::disk('sftp')->allFiles('QCS/test_folder');
Storage::disk('sftp')->delete($files);
try { Storage::disk('sftp')->deleteDirectory('QCS/test_folder'); } catch (\Exception $e) { dd($e->getMessage()); }

For both EDIT 2 and EDIT 3: file inside the folder got deleted but the file still exist, and also no error ;(

EDIT 4: Whole method I am using and the context on where I using it.

Actually, the whole method is only these few line of codes since I want to make it simpler for testing. Goal is to delete the folder testing_folder on the server. FYI we are using Synlogy's service.

Here is my code: In web.php:

Route::get('/InspectionDocument/test', 'InspectionDocumentController@test')->name('inspdoc.test');

In InspectionDocumentController.php:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Controllers\RequestController;
use DB;
use Log;
use Auth;
use File;
use Storage;
use Response;
use ZipArchive;

class InspectionDocumentController extends Controller
{
    public function __construct()
    {
    }

    // other functions...

    public function test(Request $request)
    {
        $files = Storage::disk('sftp')->allFiles('QCS/test_folder');
        Storage::disk('sftp')->delete($files);
        Storage::disk('sftp')->delete('QCS/test_folder');
        try { Storage::disk('sftp')->deleteDirectory('QCS/test_folder', false); } catch (\Exception $e) { dd($e->getMessage()); }
    }

}

For testing: First I go to the page http://localhost:8000/InspectionDocument/test. Then the page loads, without returning any error like this: enter image description here

Before running the code: enter image description here

enter image description here

After running the code: enter image description here

enter image description here

Modified date changed and the file inside got deleted.

3

There are 3 best solutions below

0
eva li On BEST ANSWER

I used a library called phpseclib https://phpseclib.com/ and I can finally delete folder. Now the function has gone live for around 2 months already

4
N69S On

Even if the documentation doesn't show it, deleteDirectory() accepts a second parameter $preserver

@src/Illuminate/Filesystem/Filesystem.php

public function deleteDirectory($directory, $preserve = false)
{
    if (! $this->isDirectory($directory)) {
        return false;
    }

    $items = new FilesystemIterator($directory);

    foreach ($items as $item) {

        if ($item->isDir() && ! $item->isLink()) {
            $this->deleteDirectory($item->getPathname());
        }

        else {
            $this->delete($item->getPathname());
        }
    }

    if (! $preserve) {
        @rmdir($directory);
    }

    return true;
}

When the second Parameter $preserve is true, the method will empty the folder without deleting it.

In your case, Storage::disk('sftp')->deleteDirectory('QCS/test_folder', true); you are asking it to keep the folder.

If you want to delete the base folder too, remove the second parameter

 Storage::disk('sftp')->deleteDirectory('QCS/test_folder');
3
symcbean On

The semantics for deleting a directory on a POSIX system are that it fails if the directory is not empty (rmdir). There are a lot of layers of abstraction between your PHP code and the remote filesystem, but I would expect that code implementing the functionality would still conform to the standard behaviour. However I see that the documentation you linked explicitly says otherwise. I suspect the documentation is wrong and the implementation is correct.

You could very this by checking the audit logging on the remote system.

Or it may simply be a permissions issue. Did you check?