Đây là bài viết Phần 3 nằm trong series: Laravel File Upload

Trong 2 phần trước, mình đã chia sẻ cách tạo form file upload cơ bản và cách kiểm tra (valdiation) file upload trong Laravel. Tuy nhiên, form upload hiện tại đang bị giới hạn chỉ chọn được 1 file duy nhất.

Bài viết [Phần 3] hôm nay sẽ hướng dẫn cách upload cùng lúc nhiều file cùng cách xác thực và xử lý các file được upload.

I. Chỉnh sửa lại form upload

Chỉnh sửa lại phần form trong upload.blade.php, thay đổi các thông số của tag input: name=file thành name=files[], id=file thành id=files, bổ sung thêm thông số multiple. Cập nhật luôn thông số của tag label: for=file thành for=files

<form action="{{ route("upload.store") }}" method="POST" enctype="multipart/form-data" class="space-y-4">
            @csrf
            <div>
                <label for="files" class="block text-sm font-medium text-gray-700 mb-1">Choose file</label>
                <input type="file" name="files[]" id="files" multiple
                    class="block w-full text-sm text-gray-500
                              file:mr-4 file:py-2 file:px-4
                              file:rounded-full file:border-0
                              file:text-sm file:font-semibold
                              file:bg-blue-50 file:text-blue-700
                              hover:file:bg-blue-100" />
            </div>
            <button type="submit"
                class="w-full bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">
                Upload
            </button>
        </form>Code language: HTML, XML (xml)

II. Cập nhật Validation Rule trong Controller

Cập nhật phần validation trong UploadController.php cho phù hợp với đối tượng mới files: là một array (tiếng Việt hình như gọi là mảng?) gồm thông tin của nhiều file khác nhau.

        $request->validate([
            'files' => 'required|array', // Tên input là 'files[]' trong HTML
            'files.*' => 'required|image|mimes:jpg,jpeg,png|max:2048', // max = 2MB mỗi file
        ]);Code language: PHP (php)

III. Xử lý file upload trong Controller

Chỉnh sửa lại code trong UploadController để phù hợp với thiết lập mới: upload nhiều file cùng lúc

        // Tạo biến mới để lưu đường dẫn và tên file gốc
        $storedFilePaths = []; // Array lưu đường dẫn các file đã lưu thành công
        $originalFilenames = []; // Array lưu tên gốc của các file
        $uploadedFiles = $request->file('files'); // Lấy array các đối tượng file đã upload
        $numberOfFiles = count($uploadedFiles); // Đếm số lượng file đã upload


        // Lặp qua từng file trong array $uploadedFiles
        foreach ($uploadedFiles as $file) {

            // Lấy tên file gốc từ client
            $originalFilename = $file->getClientOriginalName();
            $originalFilenames[] = $originalFilename; // Thêm tên gốc vào array

            // Chuẩn bị các phần của tên file
            $filenameWithoutExtension = pathinfo($originalFilename, PATHINFO_FILENAME); // Lấy tên file không có phần mở rộng
            $extension = $file->getClientOriginalExtension(); // Lấy phần mở rộng
            $directory = 'uploads'; // Thư mục lưu file trên disk
            $disk = 'public'; // Disk public sẽ sử dụng (được định nghĩa trong config/filesystems.php)

            // Xác định tên file duy nhất
            $finalFilename = $originalFilename; // Bắt đầu với tên gốc
            $counter = 1;

            // Kiểm tra xem file đã tồn tại chưa
            while (Storage::disk($disk)->exists($directory . '/' . $finalFilename)) {
                // Nếu tồn tại, tạo tên mới với hậu tố 1,2,3,...
                $finalFilename = $filenameWithoutExtension . '-' . $counter . '.' . $extension;
                $counter++;
            }

            // Lưu file bằng storeAs với tên file mới
            $storedFilePath = $file->storeAs($directory, $finalFilename, $disk); // Trả về đường dẫn tương đối: 'uploads/ten_file_cuoi_cung.jpg'
            $storedFilePaths[] = $storedFilePath; // Thêm đường dẫn file đã lưu vào array $storedFilePaths
        }

        // Chuyển hướng về trang trước đó
        return back()->with('success', 'You have successfully uploaded ' . $numberOfFiles . ' files')
            // Gửi kèm array các đường dẫn file đã lưu vào session flash data với key 'stored_paths'
            ->with('stored_paths', $storedFilePaths)
            // Gửi kèm array các tên file gốc vào session flash data với key 'original_filenames'
            ->with('original_filenames', $originalFilenames);Code language: PHP (php)

IV. Hiển thị các files đã upload

Chỉnh sửa lại phần hiển thị file đã upload trong upload.blade.php

            @if (session("stored_paths") && is_array(session("stored_paths")))
                <div class="mt-4">
                    <p>Uploaded Files:</p>
                     {{-- Lặp qua array các đường dẫn file đã lưu. $index là chỉ số, $path là đường dẫn --}}
                    @foreach (session("stored_paths") as $index => $path)
                        <div class="border p-4 mt-2">
                            <p class="text-sm text-gray-600">Original Filename:
                                {{ session("original_filenames")[$index] }}
                            </p>
                            <p class="text-sm text-gray-600">Stored Path: {{ $path }}</p>
                            <img src="{{ $path }}" alt="Uploaded Image {{ $index + 1 }}"
                                class="mt-2 rounded max-w-full h-auto border">
                        </div>
                    @endforeach
                </div>
            @endifCode language: Bash (bash)

Kiểm tra thành quả. Mọi thứ hoạt động đúng như ý muốn 🎉

V. Lời kết

Trong [Phần 3] này, mình đã chia sẻ:

  • Cập nhật form upload để có thể upload cùng lúc nhiều file
  • Chỉnh sửa lại validation rule khi upload nhiều file
  • Cách xử lý file upload khi upload nhiều file
  • Hiển thị các files đã upload ra front end.

🔗 Mã nguồn

Tham khảo mã nguồn sử dụng trong [Phần 3] ở đây: https://github.com/10h30/laravel-file-upload-series/tree/part-3-multiple-file-upload

🔜 Phần 4: Hiển thị & xoá file

Sau khi đã hỗ trợ upload nhiều file, bước tiếp theo mình cần làm quản lý các file đã upload:

  • Hiển thị danh sách file đã được lưu
  • Cho phép xoá file không còn sử dụng
  • Lưu thông tin file vào database để dễ tra cứu và mở rộng

Trong [Phần 4], chúng ta sẽ xây dựng chức năng hiển thị và xoá file, đồng thời liên kết việc upload với database bằng một model Upload.

Hẹn gặp bạn ở [Phần 4] sẽ được ra lò vào tối Chủ nhật – 11/05/2025!

Nếu bạn cần hỗ trợ kỹ thuật miễn phí, vui lòng gửi câu hỏi trực tiếp ở phần Thảo luận bên dưới, mình sẽ trả lời trong thời gian sớm nhất.

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *


Bạn cần hỗ trợ kỹ thuật chuyên sâu?

Khám phá các gói dịch vụ giúp bạn tối ưu công việc và vận hành hệ thống hiệu quả hơn. Từ chăm sóc website đến hỗ trợ kỹ thuật, mọi thứ đều linh hoạt và phù hợp với nhu cầu của bạn.