Skip to content
Thuan Bui's Blog
Go back

File Upload trong Laravel - [Phần 9] Nâng cấp giao diện upload file với FilePond

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:

  1. 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.

  2. Phần 4: Quản lý file đã upload bằng database, hiển thị danh sách và cho phép xoá file.

  3. 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).

  4. Phần 7: Tạo ảnh thu nhỏ (thumbnail) bằng Intervention Image để tối ưu hiển thị.

  5. 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:

💡 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.

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"
/>

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>

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" />

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>

Ở đâ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"
/>

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>

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>

Các thiết lập mới:

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:

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-9-drag-drop-upload

🔜 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.


Share this post on:

Previous Post
File Upload trong Laravel - [Phần 10] Upload file tự động với Livewire 3
Next Post
File Upload trong Laravel - [Phần 8] Quản lý ảnh nâng cao với Spatie Media Library