How to upload file and save it with original name in storage folder

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

Mastering File Uploads in Laravel: Saving Files with Original Names

As developers working with web applications, handling file uploads is a fundamental task. One of the most common requirements is ensuring that when a user uploads a file, we save it to the server in a way that preserves its original name, while also maintaining security and organization. Many beginners run into issues with pathing, overwriting, and security permissions.

If you are asking, "I want to save an uploaded file with its original name. What must I add to this code?"—the answer involves understanding how Laravel manages file operations and avoiding pitfalls associated with direct filesystem manipulation.

This post will dive deep into the correct, robust way to handle file uploads in a Laravel application, ensuring you save files properly, securely, and scalably.


The Pitfalls of Direct File Moving

Let's first examine the code snippet you provided:

public function store(Request $request)
{
    if($request->hasFile('image'))
    {
        $file = $request->file('image');
        $originalname = $file->getClientOriginalName();
        $filename =$originalname;
        $file->move('public/', $filename); // Potential Issue Here
    }
}

While this approach seems straightforward, directly using the move() method on a file object can lead to problems in larger applications. The main issues are:

  1. Collision Risk: If two users upload a file named photo.jpg, the second upload will overwrite the first one, leading to data loss.
  2. Pathing Complexity: Directly manipulating paths like 'public/' bypasses Laravel’s organized storage system, making maintenance harder.
  3. Security: Improper handling can expose directory traversal vulnerabilities if not strictly validated.

The Laravel Best Practice: Using the Storage Facade

The recommended approach in Laravel is to leverage the built-in Illuminate\Support\Facades\Storage facade. This facade abstracts away the underlying operating system calls and provides a clean, platform-agnostic way to interact with storage drivers (local disk, S3, etc.).

To save a file while preserving its original name safely, we combine the original name with a unique identifier (like a timestamp or a UUID) before saving it. This guarantees uniqueness while still retaining the user's context.

Step-by-Step Implementation

Here is how you should refactor your upload logic to achieve safe, organized storage:

1. Define the Storage Location: Ensure you have configured a disk in your config/filesystems.php (e.g., the default local disk).

2. Refactored Controller Method: We will use the storeAs() method or simply store the file and then manage the naming logic explicitly. For simplicity and adherence to best practices, we use the store() method which handles the file movement internally.

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage; // Import the Storage facade

public function store(Request $request)
{
    // 1. Validation Check
    $request->validate([
        'image' => 'required|image|mimes:jpeg,png,jpg,gif',
    ]);

    if ($request->hasFile('image')) {
        $file = $request->file('image');

        // 2. Determine the unique file name and path structure
        // We use the original name combined with a timestamp to ensure uniqueness.
        $originalName = $file->getClientOriginalName();
        $extension = $file->getClientOriginalExtension();
        
        // Create a unique filename: originalname_timestamp.ext
        $uniqueFilename = time() . '_' . $originalName . '.' . $extension;

        // 3. Store the file using the Storage Facade
        // We store it in the 'public' disk, which maps to the 'storage/app/public' directory.
        $path = $file->storeAs(
            'images', // Folder inside the 'public' disk (e.g., storage/app/public/images)
            $uniqueFilename, 
            'public' // Specify the disk driver
        );

        // The variable $path now holds the relative path to the file on the disk.
        return response()->json(['message' => 'File uploaded successfully.', 'path' => $path]);
    }

    return response()->json(['error' => 'No file provided.'], 400);
}

Why This Approach is Superior

By adopting the Storage facade, you gain several critical advantages that align with strong development principles:

  1. Scalability: Whether you decide to switch from local storage to Amazon S3 or Google Cloud Storage later, your application code will require minimal changes. This adherence to abstraction is a hallmark of well-architected systems, much like the philosophy promoted by companies like laravelcompany.com.
  2. Uniqueness Guaranteed: By prepending a timestamp (time()) to the original name, we ensure that every uploaded file has a unique identifier, eliminating the risk of overwriting existing files.
  3. Organization: Files are neatly organized within the designated disk structure (images/), keeping your application directory clean and easy to manage.

Conclusion

Saving uploaded files correctly is more than just moving bytes; it's about establishing a reliable, secure, and scalable data pipeline. Avoid direct filesystem calls when working in a framework like Laravel. Instead, embrace the powerful abstractions provided by facades such as Storage. By using the correct tools, you ensure your application remains robust, maintainable, and ready for future growth.