Alex
Alex

Reputation: 4774

File not found at path when trying to copy

I'm trying to copy a file from one location to another. I'm pretty sure the location is correct, but I'm still getting the error in the title.

Here's some code:

$oDirectory = new \RecursiveDirectoryIterator($extractFolder.'/res');
$oIterator = new \RecursiveIteratorIterator($oDirectory);
foreach($oIterator as $oFile) {
    if ($oFile->getFilename() == 'icon.png') {
        $icons[filesize($oFile->getPath().'/icon.png')] = $oFile->getPath().'/icon.png';
    }
}
asort($icons);
print_r($icons);
$icon_source = end($icons);
echo $icon_source;
$generated_icon_file = str_slug($packagename.$version).'.png';
Storage::copy($icon_source, $generated_icon_file);

The print_r returns (which means the files exist):

Array ( [19950] => /var/www/apk.land/storage/extracted_apks/res/drawable-xxhdpi-v4/icon.png [31791] => /var/www/apk.land/storage/extracted_apks/res/drawable-xxxhdpi-v4/icon.png [6979] => /var/www/apk.land/storage/extracted_apks/res/drawable-hdpi-v4/icon.png [10954] => /var/www/apk.land/storage/extracted_apks/res/drawable-xhdpi-v4/icon.png )

The echo returns:

/var/www/apk.land/storage/extracted_apks/res/drawable-xxxhdpi-v4/icon.png

And the exact error is:

File not found at path: var/www/apk.land/storage/extracted_apks/res/drawable-xxxhdpi-v4/icon.png

P.S. PHP's copy function works just great.

I can't find the problem here.

Any suggestions?

Upvotes: 28

Views: 7961

Answers (5)

aitbella
aitbella

Reputation: 1095

you have to choose the right disk somthing like this

$file2 ='public/'.$page->thumbnail;

$destination = 'public/bundles/ttt.png';

if( Storage::disk('local')->exists($file2)){

      Storage::disk('local')->copy($file2,$destination);
 }

Upvotes: 0

shock_gone_wild
shock_gone_wild

Reputation: 6740

First of all, if you are using Laravel's Storage Facade and with that the underlying Flysystem you have to know, that it is not intended to work with absolute paths like you did. The benefit of that is, that you could potentially work with different storage disks, that all have own configurations, that can be set in your config/filesystems.php file.

Assuming you did not change anythig there, the default "disk" would be local with an root of storage_path('app') ( = the path to your laravel storage folder/app )

If you want to know, why it is failing, we have to take a look at the source code you will find in the following code in the file vendor\league\flysystem\src\Filesystem.php

public function copy($path, $newpath)
{
    $path = Util::normalizePath($path); // <-- this will strip leading /
    $newpath = Util::normalizePath($newpath);
    $this->assertPresent($path); // this will cause the error in your case, because assertion cannot be fullfilled in case of missing leading / 
    $this->assertAbsent($newpath);

    return $this->getAdapter()->copy($path, $newpath); // calls the copy of your Adapter, assuming local in your case
}

So have a look, what would go on, if $this->getAdapter()->copy($path, $newpath) was called:

File (assuming local storage disk): vendor\league\flysystem\src\Adapter\Local.php

public function copy($path, $newpath)
{

    $location = $this->applyPathPrefix($path);
    $destination = $this->applyPathPrefix($newpath);
    $this->ensureDirectory(dirname($destination));
    return copy($location, $destination);
}

The line

$location = $this->applyPathPrefix($path);

will prepend the root path as defined in config/filesystems.php

'disks' => [

    'local' => [
        'driver' => 'local',
        'root'   => storage_path('app'),
    ],

As I can see in your code your files are are not stored in storage/app, so i think you have to change this to 'root' => storage_path()

So if you want to use Storage::copy() you have just to provide paths relative to that folder. And as it is hard to see, how you could achieve this, take a look at that.

    foreach($oIterator as $oFile) {
        if ($oFile->getFilename() == 'icon.png') {
            $icons[filesize($oFile->getPath().'/icon.png')] = $oIterator->getSubPath().'/icon.png';
        }
    }

There is RecursiveDirectoryIterator::getSubPath (Although quite undocumentated, which would return you the current subpath of your iterations. In your case relative to $extractFolder.'/res'.

Now you have to make sure you are calling

Storage::copy($icon_source, $generated_icon_file);

Where $icon_source and $generated_icon_file are relative to your defined 'root'.

Upvotes: 3

Insert / before var/www/apk.land/storage/extracted_apks/res/drawable-xxxhdpi-v4/icon.png

The path is relative to current directory. Buy if you add /, the path is absolute from root directory.

Upvotes: 3

Halayem Anis
Halayem Anis

Reputation: 7785

Try with File::copy($file, $dest) instead of Storage::copy($old, $new)
File::copy() is the wrapper on PHP's copy() function

Upvotes: 6

Aditya Giri
Aditya Giri

Reputation: 1836

You said that the error is like this:

File not found at path: var/www/apk.land/storage/extracted_apks/res/drawable-xxxhdpi-v4/icon.png

Here error is saying it cannot find at var/www that means it's looking for apk.land/var/www whereas your file is located somewhere at /var/www. A quick fix to this can be use file protocol. Just use it like:

file:///var/www/storage/apk.land/storage/extracted_apks/res/drawable-xxxhdpi-v4/icon.png

Upvotes: 9

Related Questions