Mahamudul Hasan Rubel
HomeBlogCoursesAboutProjectsSkillsExperiencePhotosContact
Mahamudul Hasan Rubel

Senior Software Engineer crafting high-performance web applications and SaaS platforms.

Navigation

  • Home
  • Blog
  • Courses
  • About
  • Projects
  • Skills
  • Experience
  • Photos
  • Contact

Get in Touch

Available for senior/lead roles and consulting.

bd.mhrubel@gmail.comHire Me

© 2026 Mahamudul Hasan Rubel. All rights reserved.

Built with using Next.js 16 & Tailwind v4

Back to Blog
Lesson 37 of the Laravel Fundamentals: From Zero to Your First App course
LaravelJune 25, 20263 min read

Handling File Uploads: A Laravel Beginner's Guide

Learn how to handle file uploads in Laravel, configure local storage, and manage file paths effectively to store user-provided content in your application.

LaravelPHPFile UploadsStorageWeb Developmentbackend

Previously in this course, we explored introduction to database relationships in Laravel to associate our tasks with specific categories or users. Now that we can manage relational data, it's time to add media capabilities to our Task Manager by learning how to handle file uploads.

In web development, you rarely want to store files directly in your database; instead, you store the file on the server (or a cloud provider) and save the file's path as a string in your database. Laravel makes this workflow incredibly simple through its unified filesystem abstraction.

Understanding Laravel Storage

Laravel provides a robust Storage facade that acts as a wrapper around the underlying filesystem. Whether you are storing files on your local machine, an Amazon S3 bucket, or an FTP server, the API remains the same.

By default, Laravel is configured to use the local disk. However, if you want files to be accessible via a web browser (like user-uploaded profile pictures or task attachments), you need to store them in a directory that the web server can serve, such as storage/app/public.

Step 1: Linking the Storage Directory

The storage/app/public directory is not automatically accessible to the public web browser because it sits outside the public/ folder for security reasons. To expose it, we create a symbolic link (symlink) from public/storage to storage/app/public. Run this command in your terminal:

Bash
php artisan storage:link

This command creates a shortcut so that any file uploaded to storage/app/public can be accessed via your-app.test/storage/filename.jpg.

Handling File Uploads in the Controller

To accept files, your HTML form must include the enctype="multipart/form-data" attribute. Without this, the browser will not send the file binary data to your server.

In your controller, you can access the uploaded file via the Request object. Here is a concrete example of how to store an attachment for a task:

PHP
public function store(Request $request)
{
    #6A9955">// 1. Validate the file
    $request->validate([
        'attachment' => 'required|image|mimes:jpeg,png,jpg|max:2048',
    ]);

    #6A9955">// 2. Store the file and retrieve the path
    #6A9955">// This saves the file to storage/app/public/tasks
    $path = $request->file('attachment')->store('tasks', 'public');

    #6A9955">// 3. Save the path to your database model
    Task::create([
        'title' => $request->title,
        'attachment_path' => $path,
    ]);

    return back()->with('success', 'Task created with attachment!');
}

Breaking down the code:

  • Validation: We use image|mimes:jpeg,png,jpg|max:2048 to ensure users only upload valid images under 2MB. This is a critical step to secure file uploads from the ground up.
  • store('tasks', 'public'): This method automatically generates a unique filename, places the file in storage/app/public/tasks, and returns the relative path (e.g., tasks/abc123xyz.jpg).
  • Database: We only save the string path, not the file itself.

Hands-on Exercise: Attaching Images to Tasks

  1. Update your tasks migration to include a nullable string column: $table->string('attachment_path')->nullable();.
  2. Run php artisan migrate.
  3. In your create.blade.php form, add <input type="file" name="attachment"> and ensure your form tag has enctype="multipart/form-data".
  4. Update your TasksController to handle the file upload as shown in the example above.
  5. In your index.blade.php, display the image: <img src="{{ asset('storage/' . $task->attachment_path) }}">.

Common Pitfalls

  • Forgetting enctype: If your file is missing from the $request, check your HTML form tag. It is the #1 cause of "file not found" errors.
  • Permissions: Ensure your storage folder is writable by the web server. If you get permission errors, check your local environment's folder ownership.
  • Over-relying on store(): While store() is great, for complex apps, you might need more control. If you encounter issues, look into mastering Laravel storage: a beginner’s guide to file uploads for advanced techniques like manual file naming.

Recap

We've successfully bridged the gap between user input and server-side storage. By linking our storage directory, validating file types, and using the store() method, we can now handle media attachments reliably. Remember: always validate the file type and size to keep your application secure and performant.

Up next: We will learn how to provide immediate feedback to users using Flash Messages after their file uploads are successful.

Previous lessonQuerying Related DataNext lesson Using Flash Messages for User Feedback
Back to Blog

Similar Posts

LaravelPHPJune 21, 20264 min read

Mastering Laravel Storage: A Beginner’s Guide to File Uploads

Master Laravel storage for file uploads with this practical guide. Learn how to handle local and cloud files using the filesystem facade efficiently.

Read more
LaravelJune 25, 20264 min read

Querying Related Data: Mastering Eager Loading in Laravel

Part of the course

Laravel Fundamentals: From Zero to Your First App

beginner · Lesson 37 of 52

  1. 1

    Setting Up the Local Development Environment

    4 min
  2. 2

    Installing Laravel and Exploring Directory Structure

    3 min
  3. 3

    Understanding the .env File and Configuration

    3 min

Stop the N+1 query problem in its tracks. Learn how to use eager loading in Laravel to keep your application fast and efficient as your data grows.

Read more
LaravelJune 25, 20263 min read

Introduction to Database Relationships in Laravel

Learn how to define hasMany and belongsTo relationships in Laravel. Master Eloquent database relationships to link models and access related data with ease.

Read more
  • 4

    The Laravel Application Lifecycle

    4 min
  • 5

    Initializing the Task Manager Project

    3 min
  • 6

    Defining Basic Web Routes

    4 min
  • 7

    Using Route Parameters

    3 min
  • 8

    Creating Your First Controller

    3 min
  • 9

    Returning Responses and Redirects

    3 min
  • 10

    Task Manager: Implementing the Task List Route

    3 min
  • 11

    Introduction to Blade Templating

    3 min
  • 12

    Using Blade Layouts and Sections

    3 min
  • 13

    Implementing Blade Partials

    4 min
  • 14

    Mastering Blade Directives for Loops and Conditionals

    3 min
  • 15

    Task Manager: Building the User Interface

    3 min
  • 16

    Understanding Database Migrations

    3 min
  • 17

    Working with Eloquent Models

    3 min
  • 18

    Performing Basic CRUD Operations

    3 min
  • 19

    Seeding the Database

    3 min
  • 20

    Task Manager: Displaying Real Database Records

    3 min
  • 21

    Capturing User Input from Forms

    4 min
  • 22

    Introduction to Laravel Validation

    3 min
  • 23

    Customizing Validation Error Messages

    3 min
  • 24

    Using Form Requests for Validation

    3 min
  • 25

    Introduction to Authentication

    4 min
  • 26

    Protecting Routes with Middleware

    3 min
  • 27

    Understanding CSRF Protection

    3 min
  • 28

    Preventing Mass Assignment

    3 min
  • 29

    Task Manager: Securing the Application

    3 min
  • 30

    Introduction to Route Model Binding

    3 min
  • 31

    Updating Existing Records

    3 min
  • 32

    Deleting Records

    3 min
  • 33

    Using Named Routes

    3 min
  • 34

    Task Manager: Completing CRUD Functionality

    3 min
  • 35

    Introduction to Database Relationships

    3 min
  • 36

    Querying Related Data

    4 min
  • 37

    Handling File Uploads

    3 min
  • 38

    Using Flash Messages for User Feedback

    3 min
  • 39

    Task Manager: Adding Status and Priorities

    3 min
  • 40

    Introduction to Artisan Commands

    3 min
  • 41

    Debugging with Laravel Tinker

    Coming soon
  • 42

    Understanding Service Providers

    Coming soon
  • 43

    Using View Composers

    Coming soon
  • 44

    Task Manager: Refactoring for Clean Code

    Coming soon
  • 45

    Introduction to Testing

    Coming soon
  • 46

    Testing Forms and Validation

    Coming soon
  • 47

    Using Database Transactions

    Coming soon
  • 48

    Handling Global Exceptions

    Coming soon
  • 49

    Preparing for Production

    Coming soon
  • 50

    Environment Security Best Practices

    Coming soon
  • 51

    Managing Assets in Production

    Coming soon
  • 52

    Task Manager: Deployment Preparation

    Coming soon
  • View full course