2

I'm using the league/flysystem package with the Flystem driver on laravel.

I'm currently trying to rename a directory. From my understanding, I need to use the move() method for this. On local filesystem driver, this is working fine. However, when using s3, I'm getting the following error:

"Error executing "GetObjectAcl" on "https://asgard-modules-dev.s3-eu-west-1.amazonaws.com/assets/media/test-s3?acl"; 

AWS HTTP error: Client error: `GET https://asgard-modules-dev.s3-eu-west-1.amazonaws.com/assets/media/test-s3?acl` resulted in a `404 Not Found` response:↵
<?xml version="1.0" encoding="UTF-8"?>↵

<Error><Code>NoSuchKey</Code><Message>The specified key does not exist.</Message> (truncated...)↵ 

NoSuchKey (client): The specified key does not exist. - <?xml version="1.0" encoding="UTF-8"?>↵

<Error><Code>NoSuchKey</Code><Message>The specified key does not exist.</Message><Key>assets/media/test-s3</Key><RequestId>B50AF4134D66FA68</RequestId><HostId>yliO7CUIt5PBsix/C339BrdFzrMTsKsommGc0fVOculaITBfC9CDPg2X43oXnW9RjnvRynmi39k=</HostId></Error>"

When I dump my from and to paths, I have the correct path names:

"/assets/media/test-s3" (from)
"/assets/media/test-s3333" (to)

The from path does exist at that location.

Am I missing something?

Thanks!

Nicolas Widart
  • 1,187
  • 4
  • 13
  • 30
  • What is the `acl` query on the end for? See this https://stackoverflow.com/questions/44778448/s3-giving-me-nosuchkey-error-even-when-the-key-exists – Jonathan Sep 28 '17 at 18:25
  • I don't know, I suspect it could be a possible cause. The url is generated by Flystem with the s3 adapter. – Nicolas Widart Sep 28 '17 at 18:34
  • It's hard to say what exactly is going on, but the placeholder objects for "directories" in S3 end with a `/`... if they are present at all (they don't need to be)... So you *might* need to use `...test-s3/`. However... S3 objects "in" a directory are not really "in" anything. Directories are not containers in S3 as they are on filesystems. – Michael - sqlbot Sep 28 '17 at 23:50
  • The problem here is that S3 doesn't actually have directories and thus they can't be moved. This is a technical limitation of the S3 system that Flysystem can not get around. The only solution is to manually create the new path and move all the files on by one from one path to the other. – Surya Jan 27 '20 at 01:49

1 Answers1

1

Since S3 does not allow you to move directories (as they are not actually directories) you have to manually move all the files inside and remove the old directory.

Here's some sample code of my solution:

class S3BucketService
{
    const SERVICE = 's3';

    /**
     * @param string $from
     * @param string $to
     * @return bool
     */
    public static function moveDirectory(string $from, string $to)
    {
        if (Storage::disk(static::SERVICE)->has($from)) {
            $folderContents = Storage::disk(static::SERVICE)->listContents($from, true);
            foreach ($folderContents as $content) {
                if ($content['type'] === 'file') {
                    $src  = $content['path'];
                    $dest = str_replace($from, $to, $content['path']);
                    Storage::disk(static::SERVICE)->move($src, $dest);
                }
            }

            Storage::disk(static::SERVICE)->deleteDirectory($from);
        }
    }
}

In this example I have a project folder and all files will be nested under there.

$from will be something like projectId projectname/Documents

$to will be something like projectId projectname/OtherDocumentFolder

Note: the SERVICE constant is also optional but in my project I am connecting to multiple cloud storage services and this class extends an other one and overrides the SERVICE from the parent class.

Surya
  • 129
  • 1
  • 3
  • 12