bvfi-dev's avatar

Directory and File have wrong permission on storeAs

I upload images and then handle it in a Livewire component like:

$fileName = md5($randomString . microtime()) . '.' .$this->image->extension();
$this->image->storeAs('public/images/listings/' .$listingId, $fileName);
$path = '/images/listings/' .$listingId .'/';

Then when I try to display the image:

@php
    $headerUrl = 'https://dev.<url>.plesk.page/storage';
    if($listing->images->isNotEmpty()){
        $headerUrl .= $listing->images[0]->path .$listing->images[0]->filename;
    } else {
        $headerUrl .= '/images/header.jpg';
    }
@endphp

And when I have an image uploaded for the listing, then the Alt attribute of the image is displayed with the broken image icon. I have to manually change the permissions in order for this to work. When the directory is created it has the following permissions (WinSCP): File permission image. Will be deleted after a couple of months

So, it works when I manually set the permissions to 0775, but by default, when the directory is created, it has 0700 permissions and the image file inside the directory has 0644 permissions. I host my site on a custom server managed by Plesk. Im not sure what to do. I havent changed config/filesystems.php, its the default one:

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Default Filesystem Disk
    |--------------------------------------------------------------------------
    |
    | Here you may specify the default filesystem disk that should be used
    | by the framework. The "local" disk, as well as a variety of cloud
    | based disks are available to your application. Just store away!
    |
    */

    'default' => env('FILESYSTEM_DISK', 'local'),

    /*
    |--------------------------------------------------------------------------
    | Filesystem Disks
    |--------------------------------------------------------------------------
    |
    | Here you may configure as many filesystem "disks" as you wish, and you
    | may even configure multiple disks of the same driver. Defaults have
    | been set up for each driver as an example of the required values.
    |
    | Supported Drivers: "local", "ftp", "sftp", "s3"
    |
    */

    'disks' => [

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

        'public' => [
            'driver' => 'local',
            'root' => storage_path('app/public'),
            'url' => env('APP_URL').'/storage',
            'visibility' => 'public',
            'throw' => false,
        ],

        's3' => [
            'driver' => 's3',
            'key' => env('AWS_ACCESS_KEY_ID'),
            'secret' => env('AWS_SECRET_ACCESS_KEY'),
            'region' => env('AWS_DEFAULT_REGION'),
            'bucket' => env('AWS_BUCKET'),
            'url' => env('AWS_URL'),
            'endpoint' => env('AWS_ENDPOINT'),
            'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
            'throw' => false,
        ],

    ],

    /*
    |--------------------------------------------------------------------------
    | Symbolic Links
    |--------------------------------------------------------------------------
    |
    | Here you may configure the symbolic links that will be created when the
    | `storage:link` Artisan command is executed. The array keys should be
    | the locations of the links and the values should be their targets.
    |
    */

    'links' => [
        public_path('storage') => storage_path('app/public'),
    ],

];
0 likes
5 replies
bvfi-dev's avatar

@gych Thank you for the reply. I guess I missed that in the documentation, but Im pretty sure I tried it at some point and it didnt work. So, this works fine, the image gets created:

$this->image->storeAs('public/images/listings/' .$listingId, $fileName);

However, when I change it to

$this->image->storePubliclyAs('public/images/listings/' .$listingId, $fileName);

Nothing happens, no image is stored in a folder. Images only get stored here: /storage/app/livewire-tmp I have tried:

'/images/listings/' .$listingId, $fileName
'images/listings/' .$listingId, $fileName
'public/images/listings/' .$listingId, $fileName
'/public/images/listings/' .$listingId, $fileName

None of which store any images in the folder and I cant debug this, because its a nested component and for some reason dd() and ddd() dont work for nested component. I do have Debugbar and I can addMessage(), but not sure how I can debug it. This is literally how my function beings so it has to go through the code:

public function saveImage($listingId)
    {
        $this->validate();

        //TODO: Add this random string generator to a Helper
        $randomString = collect(range(1, mt_rand(3,6)))->map(function () {
            return Str::random(mt_rand(4, 8));
        })->implode('');

        $fileName = md5($randomString . microtime()) . '.' .$this->image->extension();
        $this->image->storeAs('public/images/listings/' .$listingId, $fileName);
        $path = '/images/listings/' .$listingId .'/';

I am also pasting the filesystems.php again for the disks:

'local' => [
            'driver' => 'local',
            'root' => storage_path('app'),
            'throw' => false,
        ],
'public' => [
            'driver' => 'local',
            'root' => storage_path('app/public'),
            'url' => env('APP_URL').'/storage',
            'visibility' => 'public',
            'throw' => false,
        ],

Thanks again

krisi_gjika's avatar

the folder needs to be owned by the webserver user, www-data, as that will be the user serving the file back

1 like
bvfi-dev's avatar

@krisi_gjika [Arnold Schwarzenegger Accent]: Well, duh :D

jobborse is the weserver user. I figured out what the problem is, I needed to add a 3rd parameter to storePubliclyAs Thank you for the reply, all help is appreciated

bvfi-dev's avatar

I needed a 3rd parameter for the function, this creates the files/directories with the correct permissions: $this->image->storePubliclyAs('images/listings/' .$listingId, $fileName, 'public');

1 like

Please or to participate in this conversation.