How to Upload Images in Laravel 12: A Step-by-Step Guide

Author

Kritim Yantra

Feb 28, 2025

How to Upload Images in Laravel 12: A Step-by-Step Guide

Welcome to this comprehensive guide on uploading images in Laravel  12! Whether you're building a blog, an e-commerce site, or a social media platform, handling image uploads is a common requirement. In this tutorial, I’ll walk you through the entire process—from setting up your Laravel project to displaying the uploaded images on your website. We’ll use simple language and detailed explanations to ensure you understand each step.

By the end of this guide, you’ll be able to:

  • Set up a Laravel  12 project for image uploads
  • Create a model and migration to store image details
  • Build a controller to handle uploads and display images
  • Define routes for the upload form and submission
  • Create a Blade template for the upload form
  • Validate and store uploaded images
  • Display the uploaded images on your website

Let’s get started!

Prerequisites

  • A Laravel 12 project set up. If you don’t have one, create a new project using Composer:

composer create-project laravel/laravel your-project-name "12.*"

    
  • A database connection configured in your .env file. Laravel 12 supports MySQL, PostgreSQL, SQLite, and more.
  • Basic knowledge of Laravel concepts like models, controllers, and routes.

If you’re new to Laravel, don’t worry—I’ll explain everything as we go along.

Step 1: Create a Model and Migration

To store information about the uploaded images, we need a model and a corresponding database table. Let’s create an Image model and a migration to define the table structure.

Run this command in your terminal:


php artisan make:model Image -m
    

This generates two files:

  • app/Models/Image.php: The model file.
  • database/migrations/xxxx_xx_xx_create_images_table.php: The migration file (the timestamp will vary).

Open the migration file and update the up method to define the table columns:


use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateImagesTable extends Migration
{
    public function up()
    {
        Schema::create('images', function (Blueprint $table) {
            $table->id();
            $table->string('path'); // To store the image file path
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('images');
    }
}
    

This creates an images table with:

  • An id column for unique identification.
  • A path column to store the file path of the uploaded image.
  • Timestamps (created_at and updated_at) to track when records are added or modified.

Run the migration to create the table in your database:


php artisan migrate
    

Step 2: Create a Controller

Next, we need a controller to handle the logic for uploading and displaying images. Create an ImageController with this command:


php artisan make:controller ImageController
    

This creates a file at app/Http/Controllers/ImageController.php. Open it and add two methods:

  • index: To display the upload form and list of uploaded images.
  • upload: To handle the image upload process.

Here’s the initial structure:


namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Image;

class ImageController extends Controller
{
    public function index()
    {
        // Logic to display images
    }

    public function upload(Request $request)
    {
        // Logic to handle image upload
    }
}
    

We’ll fill in these methods later.

Step 3: Define Routes

Routes tell Laravel how to handle incoming requests. We need two routes:

  • A GET route to display the upload form and images.
  • A POST route to handle the form submission and upload the image.

Open routes/web.php and add these routes:


use App\Http\Controllers\ImageController;

Route::get('/images', [ImageController::class, 'index'])->name('images.index');
Route::post('/images', [ImageController::class, 'upload'])->name('images.upload');
    

These routes:

  • Map GET /images to the index method for displaying the form and images.
  • Map POST /images to the upload method for processing the upload.

Step 4: Create the Upload Form

Now, let’s create a Blade template for the upload form. Blade is Laravel’s templating engine, allowing us to mix HTML with dynamic content.

Create a new file at resources/views/images/index.blade.php and add this code:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Image Upload</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <div class="container mt-5">
        <h1>Upload an Image</h1>
        @if(session('success'))
            <div class="alert alert-success">{{ session('success') }}</div>
        @endif
        <form action="{{ route('images.upload') }}" method="POST" enctype="multipart/form-data" class="mb-5">
            @csrf
            <div class="form-group">
                <label for="image">Select Image</label>
                <input type="file" name="image" id="image" class="form-control" required>
            </div>
            <button type="submit" class="btn btn-primary mt-2">Upload</button>
        </form>
        <h2>Uploaded Images</h2>
        <div class="row">
            <!-- Images will be displayed here -->
        </div>
    </div>
</body>
</html>
    

Key points:

  • We use Bootstrap for styling.
  • The form includes enctype="multipart/form-data", which is essential for file uploads.
  • @csrf adds a CSRF token for security.
  • The input field lets users select an image file.

Step 5: Handle the Image Upload

Let’s implement the upload method in ImageController to process the uploaded image. Update it like this:


use Illuminate\Http\Request;
use App\Models\Image;
use Illuminate\Support\Facades\Storage;

public function upload(Request $request)
{
    // Validate the uploaded file
    $request->validate([
        'image' => 'required|image|mimes:jpeg,png,jpg,gif|max:2048', // Max 2MB
    ]);

    // Store the image in the 'public' disk
    $path = $request->file('image')->store('images', 'public');

    // Save the image path to the database
    $image = new Image();
    $image->path = $path;
    $image->save();

    // Redirect back with a success message
    return redirect()->route('images.index')->with('success', 'Image uploaded successfully!');
}
    

This code does the following:

  • Validation: Ensures the file is an image (JPEG, PNG, JPG, or GIF) and under 2MB.
  • Storage: Saves the image to storage/app/public/images using the public disk.
  • Database: Stores the file path in the images table.
  • Redirect: Returns the user to the /images page with a success message.

Step 6: Display Uploaded Images

Now, update the index method to retrieve and display the uploaded images:


public function index()
{
    $images = Image::latest()->get();
    return view('images.index', compact('images'));
}
    

This fetches all images from the database (newest first) and passes them to the index.blade.php view.

Next, update the Blade template to display the images. Add this inside the <div class="row"> element:


@foreach($images as $image)
    <div class="col-md-4 mb-3">
        <img src="{{ asset('storage/' . $image->path) }}" alt="Uploaded Image" class="img-fluid">
    </div>
@endforeach
    

This loop displays the images in a responsive grid. The asset helper generates the correct URL for each image.

Step 7: Link Storage for Public Access

To make uploaded images accessible via the browser, create a symbolic link from public/storage to storage/app/public. Run this command:


php artisan storage:link
    

This allows files in storage/app/public to be accessed publicly (e.g., at /storage/images/your-image.jpg).

Step 8: Test Your Application

Let’s test everything:

  • Start your Laravel server:

php artisan serve
    
  • Visit http://localhost:8000/images in your browser.
  • Select an image and click "Upload."
  • Check for a success message and verify the image appears below the form.

If something doesn’t work, ensure that:

  • The storage directory is writable.
  • The storage:link command ran successfully.
  • Your image meets the validation rules (file type and size).

Best Practices and Tips

  • Validation: Always validate file uploads to ensure security and data consistency.
  • Error Handling: Add logic to handle upload failures (e.g., file too large).
  • Image Resizing: Consider resizing large images server-side for better performance.
  • Multiple Uploads: Modify the form and controller to support multiple files if needed.
  • Security: Restrict uploads to safe file types to prevent malicious uploads.

Conclusion

Congratulations! You’ve built a complete image upload system in Laravel 12. You learned how to set up a model and migration, create a controller and routes, design an upload form, handle file storage, and display images on your site.

This is a solid starting point—you can expand it further by adding features like image deletion, editing, or linking images to other models (e.g., users or products). If you have questions or run into issues, feel free to leave a comment. Happy coding with Laravel!

Tags

Laravel Php

Comments

No comments yet. Be the first to comment!

Please log in to post a comment:

Continue with Google

Related Posts