Đây là bài viết Phần 9 nằm trong series: Laravel File Upload
Trong 8 phần trước của series “File Upload trong Laravel”, chúng ta đã lần lượt khám phá các khía cạnh quan trọng nhất của quá trình upload:
- Phần 1–3: Cài đặt chức năng upload cơ bản, kiểm tra dữ liệu, bảo mật, và hỗ trợ upload nhiều file một lúc.
- Phần 4: Quản lý file đã upload bằng database, hiển thị danh sách và cho phép xoá file.
- Phần 5–6: Tích hợp lưu trữ lên Amazon S3 hoặc MinIO, và tạo link truy cập tạm thời (temporary URL).
- Phần 7: Tạo ảnh thu nhỏ (thumbnail) bằng Intervention Image để tối ưu hiển thị.
- Phần 8: Ứng dụng thư viện Spatie Media Library giúp quản lý file đính kèm mạnh mẽ và linh hoạt hơn.
Toàn bộ quá trình tải upload file hiện tại đang dựa vào form input dạng type="file"
đơn giản của HTML, giao diện khá nhàm chán, và không thân thiện với người dùng.
Trong [Phần 9] này,chúng ta sẽ nâng cấp form upload bằng thư viện FilePond – một thư viện JavaScript mạnh mẽ giúp cải thiện UI/UX khi tải file:
- Hỗ trợ kéo-thả (drag-and-drop) file
- Hiển thị ảnh preview trước khi upload
- Cho phép xoá file khỏi danh sách trước khi gửi lên server
- Tự động gửi file bằng Ajax (hoặc gửi cùng form truyền thống)
💡 FilePond là thư viện. mã nguồn mở và miễn phí cho mục đích cá nhân hoặc thương mại.
Mục Lục
I. Cài đặt FilePond
Mình sẽ tích hợp FilePond vào file blade upload.blade.php
bằng cách sử dụng CDN cho đơn giản.
Chèn đoạn mã sau vào trong phần <head>
của file
<!-- FilePond CSS -->
<link href="https://unpkg.com/filepond/dist/filepond.min.css" rel="stylesheet" />
Code language: HTML, XML (xml)
Chèn code khai báo js vào trước tag </body>
<!-- FilePond JS -->
<script src="https://unpkg.com/filepond/dist/filepond.min.js"></script>
Code language: HTML, XML (xml)
II. Cập nhật form upload
Loại bỏ toàn bộ phần khai báo class=block w-full...
ra khỏi tag <input type=file...>
, FilePond sẽ tự xử lý phần giao diện của form input, nếu giữ lại class cũ sẽ gây lỗi khi kích hoạt FilePond.
Phần input giờ chỉ còn lại đơn giản gọn nhẹ thế này.
<input type="file" name="files[]" id="files" multiple data-max-files="5" />
Code language: Bash (bash)
III. Thiết lập thông số cho FilePond
Bổ sung đoạn script này vào trước tag </body>
của file upload.blade.php
<script>
// Chọn input HTML có id là "files"
const inputElement = document.querySelector('input[id="files"]');
// Khởi tạo FilePond trên input đó với các tùy chọn cấu hình
FilePond.create(inputElement, {
// Cho phép chọn nhiều file cùng lúc
allowMultiple: true,
// Gửi file lên server bằng phương pháp POST trực tiếp qua form.
storeAsFile: true,
});
</script>
Code language: HTML, XML (xml)
Ở đây mình sử dụng thông số storeAsFile: true
để yêu cầu FilePond upload file lên server bằng phương pháp POST truyền thống qua form. Do đó mình không cần cập nhật gì ở backend: UploadController
và model Upload
.
IV. Upload file với Filepond
Truy cập lại vào web app, giao diện upload giờ đã được nâng cấp xịn xò hơn hẳn.
Mình có thể bấm Browse để upload chọn file, sau đó Upload.

Mình cũng có thể kéo thả file vào ô Drag & Drop, FilePond sẽ tự động nhận diện file. Quá trình upload diễn ra ngon lành.

V. Các tính năng cao cấp của FilePond
Filepond hỗ trợ thêm nhiều tính năng hữu ích cho việc upload file: kiểm tra kích thước file, loại file, xem trước ảnh preview của file, crop file … thông qua các plugin.
Mình sẽ tích hợp 3 tính năng kiểm tra kích thước file, loại file, xem trước ảnh preview của file vào form upload.
Bổ sung khai báo style cho plugin Image Preview, chèn đoạn code sau vào phần <head>
của upload.blade.php
<link
href="https://unpkg.com/filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css"
rel="stylesheet"
/>
Code language: HTML, XML (xml)
Bổ sung khai báo các file js cho các plugin image preview
, file-validate-size
, file-validate-type
vào bên dưới phần kháo báo filepond.min.js
ở trước tag </body>
<script src="https://unpkg.com/filepond-plugin-image-preview/dist/filepond-plugin-image-preview.min.js"></script>
<script src="https://unpkg.com/filepond-plugin-file-validate-size/dist/filepond-plugin-file-validate-size.js"></script>
<script src="https://unpkg.com/filepond-plugin-file-validate-type/dist/filepond-plugin-file-validate-type.min.js"></script>
Code language: HTML, XML (xml)
Cập nhật lại phần khai báo thông số FilePond
<script>
// Register plugins
FilePond.registerPlugin(
FilePondPluginImagePreview,
FilePondPluginFileValidateSize,
FilePondPluginFileValidateType
);
// Chọn input HTML có id là "files"
const inputElement = document.querySelector('input[id="files"]');
// Khởi tạo FilePond trên input đó với các tùy chọn cấu hình
FilePond.create(inputElement, {
// Cho phép chọn nhiều file cùng lúc
allowMultiple: true,
// Số lượng tệp tối đa được phép tải lên là 5
maxFiles: 5,
// Chỉ chấp nhận các loại tệp hình ảnh (ví dụ: .jpg, .png, .gif)
acceptedFileTypes: ['image/*'],
// Kích thước tệp tối đa cho phép là 100KB
maxFileSize: '100KB',
// Thông báo hiển thị khi tệp vượt quá kích thước tối đa
labelMaxFileSizeExceeded: 'The file is too big',
// Gửi file lên server bằng phương pháp POST trực tiếp qua form.
storeAsFile: true,
// Hàm được gọi khi có cảnh báo từ FilePond
onwarning: (error, file, status) => {
// Ghi cảnh báo ra console của trình duyệt
console.warn('FilePond warning:', error, file, status);
// Hiển thị thông báo cảnh báo cho người dùng
alert('Warning: ' + error.main);
},
// Hàm được gọi khi có lỗi nghiêm trọng từ FilePond
onerror: (error, file, status) => {
// Ghi lỗi ra console của trình duyệt
console.error('FilePond error:', error, file, status);
// Hiển thị thông báo lỗi cho người dùng
alert('Error: ' + error.main);
}
});
</script>
Code language: HTML, XML (xml)
Các thiết lập mới:
- Chỉ cho phép upload cùng lúc 5 file
- Chỉ chấp nhận file ảnh
- Kích thước file lớn nhất: 100KB
- Hiển thị thông báo lỗi cho người dùng nếu thấy vi phạm
Kiểm tra lại form upload, khi chọn file, trình duyệt sẽ tự động giới hạn chỉ cho phép chọn file ảnh, các file khác sẽ bị mờ, không thể chọn để upload

Trong trường hợp mình cố ý kéo 1 file php vào, hệ thống sẽ hiện ra cảnh báo lỗi, và sẽ không upload thành công.

Trong trường hợp chọn file, ảnh file thỏa mãn điều kiện nhỏ hơn 100KB sẽ tự động hiển thị ảnh thumbnail, các file quá lớn sẽ bị từ chối cùng với lỗi The file is too big
.

Form Upload hiện giờ đã ngon lành cành đào hơn hẳn so với form upload sử dụng trước đó. Giao diện đã được cải thiện đáng kể, giúp người dùng tương tác dễ dàng và trực quan hơn nhiều.
VI. Lời kết
TTrong [Phần 9], chúng ta đã nâng cấp giao diện upload bằng cách tích hợp FilePond, một thư viện JavaScript hiện đại giúp:
- Cho phép chọn nhiều file với giao diện kéo-thả (drag-n-drop)
- Hiển thị ảnh xem trước ngay khi chọn file
- Giới hạn số lượng file, dung lượng, định dạng ảnh
- Tích hợp tốt với hệ thống backend Laravel đã xây dựng
- Sử dụng chung được với Spatie Media Library để lưu file
Nhờ FilePond, trải nghiệm người dùng khi upload ảnh trở nên trực quan, tiện lợi và chuyên nghiệp hơn nhiều so với input HTML truyền thống.
🔗 Mã nguồn
Tham khảo mã nguồn sử dụng trong [Phần 9] ở đây: https://github.com/10h30/laravel-file-upload-series/tree/part-8-spatie-media-library
🔜 Phần 10: AJAX Upload + Livewire
Trong phần tiếp theo – cũng là phần cuối của series – chúng ta sẽ học cách kết hợp FilePond với Livewire để thực hiện upload file hoàn toàn bằng AJAX, không cần reload trang. Đây sẽ là bước hoàn thiện cuối cùng cho hệ thống upload ảnh mạnh mẽ và linh hoạt.
Hẹn gặp lại bạn ở [Phần 10], sẽ được ra lò vào …. LÚC NÀO CHƯA BIẾT.
Bạn đang xem loạt bài viết: Laravel File Upload
- Phần 1: File Upload trong Laravel – [Phần 1] Tạo form, xử lý file, lưu trữ file
- Phần 2: File Upload trong Laravel – [Phần 2] Kiểm tra và bảo vệ file upload form
- Phần 3: File Upload trong Laravel – [Phần 3] Upload cùng lúc nhiều file
- Phần 4: File Upload trong Laravel – [Phần 4] Hiển thị và xoá các file đã upload
- Phần 5: File Upload trong Laravel – [Phần 5] Upload file lên Amazon S3
- Phần 6: File Upload trong Laravel – [Phần 6] Temporary URL và Upload lên MinIO (self-hosted S3)
- Phần 7: File Upload trong Laravel – [Phần 7] Tạo thumbnail (ảnh thu nhỏ) với Intervention Image
- Phần 8: File Upload trong Laravel – [Phần 8] Quản lý ảnh nâng cao với Spatie Media Library
- Phần 9: File Upload trong Laravel – [Phần 9] Nâng cấp giao diện upload file với FilePond