dbnames's avatar

Image is broken while the file itself is stored

Hello, so i was building an e-commerce website and i was in the middle of building the CRUD features for managing products. I got the problem when i try to view the products, while it's showing another attributes like the product name, price, weight, etc, the image was broken.

Here is my Controller:

public function store(Request $request)
{
		$this->validate($request, [
			'name' => 'required|string|max:100',
			'description' => 'required',
			'category_id' => 'required|exists:categories,id',
			'price' => 'required|integer',
			'weight' => 'required|integer',
			'image' => 'required|image|mimes:png,jpeg,jpg'
			]);

		if ($request->hasFile('image')) {
			$file = $request->file('image');
			$filename = time() . Str::slug($request->name) . '.' . $file->getClientOriginalExtension();
			$file->storeAs('public/products', $filename);

			$product = Product::create([
				'name' => $request->name,
				'slug' => $request->name,
				'category_id' => $request->category_id,
				'description' => $request->description,
				'image' => $filename,
				'price' => $request->price,
				'weight' => $request->weight,
				'status' => $request->status
				]);

			return redirect(route('product.index'))->with(['success' => 'Products Added']);
		}
}

And this is where i want to view the images:

forelse ($product as $row)
    	<tr>
    	     <td>
    	          <img src="{{ asset('storage/products/' . $row->image) }}" width="100px" height="100px" alt="{{ $row->name }}">
    	     </td>
    	     <td>
    	          <strong>{{ $row->name }}</strong><br>
    	          <label>Category: <span class="badge badge-info">{{ $row->category->name }}</span></label><br>
    	          <label>Weight: <span class="badge badge-info">{{ $row->weight }} gr</span></label>
    	     </td>
    	     <td>$ {{ number_format($row->price) }}</td>
    	     <td>{{ $row->created_at->format('d-m-Y') }}</td>
                                        
    	     <td>{!! $row->status_label !!}</td>
    	     <td>
    	          <form action="{{ route('product.destroy', $row->id) }}" method="post">
    	               @csrf
    	               @method('DELETE')
    	               <a href="{{ route('product.edit', $row->id) }}" class="btn btn-warning btn sm">Edit</a>
    	               <button class="btn btn-danger btn-sm">Delete</button>
    	          </form>
    	     </td>
         </tr>
         @empty
         <tr>
    	<td colspan="5" class="text-center">No Data</td>
         </tr>
    @endforelse

Before it was showing, but when i try to change to another template for my website, not long after this it suddenly broken. And when i checked the file in storage/app/public/products/ directory the files is in there and it can be deleted or even updated from the administrator panel but i still can't figure out what causing it.

Is there any suggestion?

Thank you.

0 likes
7 replies
jlrdw's avatar

First, have you used the browser dev tools to see what's going on?

So if you only had this:

<img src="{{ asset('storage/products/' . $row->image) }}" width="100px" height="100px" alt="{{ $row->name }}">

Does the image show?

If so add a little at a time to that view and see where the problem begins.

1 like
IlijaTatalovic's avatar

If you did not change anything in config/filesystems.php, Laravel by default saves files files in storage/app/public, and to make these files accessible from the web, you should create a symbolic link from public/storage to storage/app/public wtih command php artisan storage:link. Then, I think you should change your code to save image like this

$file->storeAs('products', $filename);

and access it like this:

     \Storage::disk('public')->url($row->image);
  
2 likes
dbnames's avatar

Sorry for my late reply and thank you for your reply! I tried your suggestion but the images is still broken and it makes another new directory (storage/app/products), the files is stored in there instead of storage/app/public/products directory

drewdan's avatar
$file->storeAs('products', $filename, 'public');

I have not checked the API to make sure that works, but might be worth trying that, see if passing it the relevant driver helps.

1 like
Snapey's avatar

check the symlink.

With your local file browser, you should be able to see the file in storage/app/public/products AND in public/storage/products

1 like
dbnames's avatar
dbnames
OP
Best Answer
Level 1

Thank you sir for your suggestion!

The answer is apparently i just need to revert the storage symlink:

rm public/storage

And then connect it again:

php artisan storage:link

Thank you all for all of your suggestions, i really appreciate it!

Please or to participate in this conversation.