theUnforgiven's avatar

Creating a new folder in the public folder on the fly

Hi all,

Hope everyone is enjoying the new 5.4....

Using 5.4 I want to use the Intervention lib to re-size images uploaded but rather than just store in the public folder I want to store as public/uploads/company_name the company name will be created in the store method.

Like this.

$sub = new Subscribers;
        if ($request->hasFile('file')){
            $file = $request->file('file');
            $name = str_random(30).'.'.$file->getClientOriginalExtension();
            $image = Image::make($request->file('file')->getRealPath())->resize(110, 65, function ($constraint) {
                $constraint->aspectRatio();
            });
            // Make new company directory
            $dir = Storage::makeDirectory($request->company_name);
            
            $image->save(public_path() . '/uploads/' . $dir . '/' . $name);
            $sub->logo = $name;
        }
        $sub->user_id = null;
        $sub->company_name = $request->company_name;
        $sub->contact_name = $request->contact_name;
        $sub->contact_number = $request->contact_number;
        $sub->email_address = $request->email_address;
        $sub->reg_address = $request->reg_address;
        $sub->no_branches = $request->no_branches;
        $sub->postcode = $request->postcode;
        $sub->category = null;
        $sub->registered_date = Carbon::now();
        $sub->save();

Im trying to create the directory with $dir = Storage::makeDirectory($request->company_name); but this is showing an error of:

NotWritableException in Image.php line 143:
Can't write image data to path 

Wondered if anyone else has found a solution to this roadblock :)

Thanks in advance.

0 likes
13 replies
SaeedPrez's avatar

Hi @theUnforgiven

Storate::makeDirectory() returns a boolean (true/false), saving the boolean response into $dir and then using it in the path generates an error as expected.

            // Make new company directory
            $companyName = str_slug($request->company_name, '_');
            Storage::makeDirectory($companyName);
            
            $filePath = storage_path($companyName . '/' . $name);

            $image->save($filePath);

I would probably also use str_slug() for the company name in path, just in case.

Edit1: Added example.

Edit2: Damn, by the time I edit this, there are 10 new answers.. people are so quick ☺

Edit3: Updated to storage_path() as of Snapey's suggestion

WebKenth's avatar
$image->save(public_path() . '/uploads/' . $request->company_name . '/' . $name);

and remove the

$dir = Storage::makeDirectory($request->company_name);

The image save function will automatically make any subfolders needed

Snapey's avatar
Snapey
Best Answer
Level 122

can company name contain a space? You may need to turn it into something that is safe for folders.

You also need to catch someone trying to create a company name like '../../xyz' and then creating a folder (or worse) somewhere you don't want

Perhaps the folder should be something you decide and then you link it to the company in their model.

Storage::makeDirectory('$path'); expects a path relative to the storage folder.

So, assuming you have shared storage public folder with a symbolic link php artisan storage:link and you are using the local storage driver then your command needs to be like Storage::makeDirectory("/app/public/uploads/{$company}");

Note that makeDirectory returns a true or false and not the folder it created so $dir=Storage::makeDirectory is not going to give the result you expected

Edit: obviously I typed all this whilst my learned colleagues were replying

theUnforgiven's avatar

Just tried the following:

$companyDir = str_replace(' ','_', strtolower($request->company_name));
$image->save(public_path() . '/uploads/' . $companyDir . '/' . $name);

Which does show as created by error again:

Can't write image data to path (/Users/code/dn/public/uploads/Testing/xsLXwUOb4omqYwKvaatcdFQU8H9Hqw.jpg)
SaeedPrez's avatar

@Snapey

I think someone created a suggestion thread for this, to show if other people are replying.. It would be a welcomed feature.

Snapey's avatar

Web Developer's Mantra NEVER TRUST USER INPUT

second point... You are trying to create the image in the public folder and not the storage folder. If your web server is setup correctly you should not have permission to do that.

1 like
WebKenth's avatar

You could use Str::slug($company_name) to create a safe name for folders

Snapey's avatar

But you have already been advised how to fix the saving...

Please or to participate in this conversation.