3

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 would provide more information if you need it.

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

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.

eva li
  • 31
  • 3
  • What does the the following output? try { Storage::disk('sftp')->deleteDirectory('path/to/folder', true); } catch (\Exception $e) { dd($e->getMessage()); } – Karl Hill Jun 01 '23 at 07:23
  • @KarlHill Thanks so much for your reply. Just tried and no execption was caught. Also if i do dd(Storage::disk('sftp')->has('path/to/folder'));, it also return true. What should I do next? Thanks a lot!!!! – eva li Jun 01 '23 at 07:33
  • Does SFTP_USERNAME have the correct permissions? – Karl Hill Jun 01 '23 at 07:43
  • @Karl Hill Thanks for your comment again. Yes this account has full right. And I can delete folder using WinSCP. – eva li Jun 01 '23 at 08:04
  • @evali try to delete all files first in that directory and then delete the directory. – francisco Jun 01 '23 at 08:26
  • @francisco Thanks for your reply, please kindly see my EDIT 2. I did that to delete all files first and it did deleted all files inside the folder, but the folder still exist ;( and also no error – eva li Jun 01 '23 at 08:46
  • The method behave as expected. Check the answer below. – N69S Jun 01 '23 at 08:52
  • $files = Storage::disk('sftp')->allFiles('QCS/test_folder'); if (count($files) === 0) { Storage::disk('sftp')->deleteDirectory('QCS/test_folder', true); } else { // Directory is not empty, do something } – Karl Hill Jun 01 '23 at 08:54

2 Answers2

1

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');
N69S
  • 16,110
  • 3
  • 22
  • 36
  • thanks so much for your detailed explaination. However, I also treid to remove the second parameter and ran the code again (please kindly refer to EDIT 3), the files inside got deleted again but the file still exist. Could you please provide me more insight on how to solve this problem. Really really thanks a lot!!!!! – eva li Jun 01 '23 at 09:15
  • @evali did you refresh whatever you are using to check if the folder still exists ? – N69S Jun 01 '23 at 11:19
  • Hi!! I did refresh everytime but the folder still here ;( – eva li Jun 02 '23 at 01:10
  • @evali the try catch is not needed as the `deleteDirectory()` doesnt throw an exception and the `rmdir` inside of it is silence with `@`. The method return true or false if the directory is deleted or not. you can test on that. second, you can remove the silencing operator `@` in the vendor file to check what it return (most likely a permission issue with the owner of the folder). Third, you dont need to delete the files beforehand, calling only `deleteDirectory()` is enough. – N69S Jun 02 '23 at 10:39
0

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?

symcbean
  • 47,736
  • 6
  • 59
  • 94
  • Hello! Thanks for your reply. I tried to delete an empty folder / folder with files. Also tried to delete the files inside the folder first, then delete the folder. All of these attempts fails ;( For the permission issue. The colleague who maintain the server said all rights have been granted to this account already. Seems I am the only one who has this problem and I wonder what's wrong with my code ;( – eva li Jun 02 '23 at 01:15
  • @evali mind sharing the whole method you are using and the context on where you are using it (request/cron/queue) ? – N69S Jun 02 '23 at 02:41
  • @N69S Hey thanks for your reply again! So my work is to build an UI for users to upload / download / delete files on the server through a laravel application. And the whole method is just a few lines of code (Please kindly see my EDIT 4). Again, thank you so much for taking your time to help me! ;) – eva li Jun 02 '23 at 04:33