Slaveworx
Slaveworx

Reputation: 611

Laravel Image Upload not saving to public folder

I am struggling with this image upload system. It is supposed to upload an image that will be attached to a post (each post has 1 image).

Everything seems to be working fine, the problem is that when I check the database for the image path, I see a path to a random temporary file and the image doesn't even get uploaded to the right folder inside the app public folder.

Check the logic below:

PostController.php

public function store(Request $request)
{
    $post = new Post;

    $request->validate([
        'title' => 'required',
        'description' => 'required',
        'slug' => 'required',
        'message' => 'required',
        'user' => 'required',
        'post_image' => 'image|mimes:jpeg,png,jpg,gif|max:2048'
        ]);

        if ($request->has('post_image')) {
            $image = $request->file('post_image');
            $name = Str::slug($request->input('title')).'_'.time();
            $folder = '/uploads/images/';
            $filePath = $folder . $name. '.' . $image->getClientOriginalExtension();
            $this->uploadOne($image, $folder, 'public', $name);
            $post->post_image = Storage::url($filePath);;
        }

    Post::create($request->all());

    return \Redirect::to('admin')->with('success','Great! Post created successfully.');
}

UploadTrait.php

trait UploadTrait
{
    public function uploadOne(UploadedFile $uploadedFile, $folder = null, $disk = 'public', $filename = null)
    {
        $name = !is_null($filename) ? $filename : Str::random(25);

        $file = $uploadedFile->storeAs($folder, $name.'.'.$uploadedFile->getClientOriginalExtension(), $disk);

        return $file;
    }
}

Post.php (model)

    class Post extends Model
{
    protected $fillable = [
        'title',
        'description',
        'slug',
        'message',
        'user',
        'post_image'
       ];


    public function getImageAttribute(){
        return $this->post_image;
    }

}

Create.blade.php

<form action="{{ route('blog.store') }}" method="POST" name="add_post" role="form" enctype="multipart/form-data">
{{ csrf_field() }}

<h1>New Post</h1>
<div role="separator" class="dropdown-divider"></div> 

<div class="form-row">
    <div class="form-group col-12 col-md-6">
      <label for="title">Post Title</label>
      <input type="text" autocomplete="off" class="form-control" id="title" name="title" placeholder="Your post title" required>
      <span class="text-danger">{{ $errors->first('title') }}</span>
    </div>

    <div class="form-group col-12 col-md-6">
        <label for="slug">Slug</label>
      <input type="text" autocomplete="off" class="form-control" id="slug" name="slug" placeholder="Write post slug" required>
      <span class="text-danger">{{ $errors->first('slug') }}</span>
    </div>
</div>

<div class="form-row">
    <div class="form-group col-12 col-md-12">
        <label for="description">Post Description</label>
      <textarea class="form-control" id="description" name="description" placeholder="Enter a small description for your post" required></textarea>
      <span class="text-danger">{{ $errors->first('description') }}</span>
    </div>


</div>


    <div class="badge badge-warning badge-pill">Message</div>
    <div role="separator" class="dropdown-divider"></div>

 <div class="form-row">
    <div class="form-group col-md-12">
        <textarea class="form-control" col="4" id="message" name="message"></textarea>
        <span class="text-danger">{{ $errors->first('message') }}</span>
    </div>

</div>

<input type="hidden" value="{{ Auth::user()->name }}" name="user">

<input id="post_image" type="file" class="form-control" name="post_image">



  <button type="submit" class="btn btn-warning btn-block">Create Post</button>

</form>

Thank you for your help!

Regards, Tiago

Upvotes: 0

Views: 10964

Answers (4)

Max Barannyk
Max Barannyk

Reputation: 21

Input in form

<form method="POST" enctype="multipart/form-data" action="/url">
     <input id="category_logo" type="file" class="form-control"  name="category_logo">...

Code in controller

$category = Category::find($id);
if($request->has('category_logo')) {
                $image = $request->file('category_logo');
                $category->category_logo = $image->getClientOriginalName();
                $image->move(public_path('img/logo'), $image->getClientOriginalName());
            }
            $category->save();

Works for me!

Upvotes: 0

Slaveworx
Slaveworx

Reputation: 611

Thank you David! I managed to correct the path that gets saved to the database, but the files are not getting uploaded (even though the path in database says /uploads/images/something.png, when i check the folder, the image is not there.. there is not even an uploads folder. This is the method I have now with your suggestions:

public function store(Request $request)
    {
        $request->validate([
            'title' => 'required',
            'description' => 'required',
            'slug' => 'required',
            'message' => 'required',
            'user' => 'required',
            'post_image' => 'image|mimes:jpeg,png,jpg,gif|max:2048'
            ]);

            if ($request->has('post_image')) {
                $image = $request->file('post_image');
                $name = Str::slug($request->input('title')).'_'.time();
                $folder = '/uploads/images';
                $filePath = $folder . $name. '.' . $image->getClientOriginalExtension();
                $this->uploadOne($image, $folder, 'public', $name);
                $image_path = Storage::disk('public')->putFile('uploads/images', $request->file('post_image'));
                $request['image_path'] = $image_path;

            }

            $post = new Post;
            $post->title = $request->title;
            $post->description = $request->description;
            $post->slug = $request->slug;
            $post->message = $request->message;
            $post->user = $request->user;
            $post->post_image = $request->image_path;
            $post->save();

        return \Redirect::to('admin')->with('success','Great! Post created successfully.');
    }

Upvotes: 0

David Garay
David Garay

Reputation: 24

You can use directly the functions provided by Laravel itself

$image_path = Storage::disk('public')->putFile('folders/inside/public', $request->file('post_image'));

Notice Storage::disk('public') that specifies the public folder.

Then you can update your request array with $request['image_path'] = $image_path and save it like you're currently doing or you cant still use your $post = new Post; and set every input data like $post->title = $request->title; then save like $post->save();

Upvotes: 1

A. Dabak
A. Dabak

Reputation: 870

You did not save the image path in the database on the created post

$post = new Post; //here you have created an empty Post object
...
$post->post_image = Storage::url($filePath); //here you assigned the post_image to the empty object.

Post::create($request->all());// here you create a new POST object with the request data, which does not contain the post_image

Upvotes: 0

Related Questions