Upload hình ảnh trong laravel với spatie media library

Ở bài upload và remove hình ảnh trong laravel và upload nhiều ảnh trong laravel bằng ajax chúng ta đã tìm hiểu cách upload hình ảnh trong laravel. Ở bài viết này chúng ta cùng tìm hiểu thêm một cách upload hình ảnh khác cho ứng dụng viết bằng laravel với sự hỗ trợ của thư viện spatie media library hay laravel medialibrary.
Thư viện spatie media library giúp chúng ta đơn giản hoá đi rất nhiều trong việc xử lý upload hình ảnh cũng như lưu trữ chúng. Các file anh sẽ được lưu vào từng thư mục riêng biệt và đặt tên theo ID được tạo ra trong table media. Việc còn lại cuả chúng ta là xây dựng ứng dụng và giao diện xử lý việc upload hình ảnh.

Cài đặt và cấu hình spatie media library để upload hình ảnh trong laravel
Tôi sẽ không nói đến đến cách cài đặt laravel như những bài viết hướng dẫn nước ngoài thường làm. Vì khi tìm hiểu upload hình ảnh trong laravel thì chắc chắn bạn đã làm việc rất nhiều với laravel. Vậy nên ta sẽ đi trực tiếp vào cách cài đặt spatie media library.
Đầu tiên, chúng ta cài đặt Spatie Media Library bằng Composer, bằng cách mở terminal và chạy dòng lệnh dưới đây sau:
composer require spatie/laravel-medialibrary
Sau khi cài đặt xong, ta thêm ServiceProvider và Facade vào file config/app.php:
'providers' => [
// ...
Spatie\MediaLibrary\MediaLibraryServiceProvider::class,
],
'aliases' => [
// ...
'MediaLibrary' => Spatie\MediaLibrary\MediaLibraryFacade::class,
],
Sau đó, chạy lệnh để xuất cấu hình:
php artisan vendor:publish --provider="Spatie\MediaLibrary\MediaLibraryServiceProvider" --tag="config"
Và để tạo bảng lưu trữ thông tin về hình ảnh hay file tải lên ta cần chạy lệnh migration như dưới:
php artisan migrate
Bạn cũng có thể tham khảo chi tiết cách cài đặt spatie media library cung như cách cấu hình chúng tại trang chủ spatie.be
Upload và hiển thị hình ảnh bằng spatie media library
Để có thể chạy được thư viện spatie media library bạn cần phải thực hiện bước dưới đây để có thẻ upload hình ảnh trong ứng dụng của mình. Bạn mở model (giả sử là model Post) mà bạn sử dụng để upload hình ảnh và thêm vào các thông tin dưới đây:
use Illuminate\Database\Eloquent\Model;
use Spatie\MediaLibrary\HasMedia\HasMedia;
use Spatie\MediaLibrary\HasMedia\HasMediaTrait;
class Post extends Model implements HasMedia
{
use HasMediaTrait;
// ...
}
Trong controller chúng ta có thể thêm 1 hoặc nhiều hình ảnh theo cú pháp sẵn có mà spatie media library đã xây dựng.
use Illuminate\Http\Request;
public function uploadImage(Request $request, $postId)
{
$post = Post::findOrFail($postId);
$request->validate([
'image' => 'required|image|mimes:jpeg,png,jpg,gif|max:2048',
]);
$post->addMedia($request->file('image'))
->toMediaCollection('images');
return redirect()->back()->with('success', 'Hình ảnh đã được tải lên thành công.');
}
Tất cả những phần giới thiệu ở trên đã được Spatie làm giúp bạn, phân việc còn lại là xây dựng giao diện upload hình ảnh trong html. Bạn có thể sử dụng thêm các thư viện javascript có sẵn để upload hình ảnh. Tuy nhiên ở bài viết này mình sẽ làm một mẫu upload hình ảnh trong html kết hợp với js đơn giản mà không cần đến các thư viện của bên thứ 3.
html cho upload hình ảnh
<div class="form-group row">
<label class="col-lg-3 col-form-label">Bill images</label>
<div class="col-lg-9 ">
<div class="files-container">
<div id="image_uploads" class="files-area"></div>
<label for="input_upload" class="files-add"><i class='bx bxs-cloud-upload'></i>Upload</label>
<input id="input_upload" type="file" name="image_uploads[]"
class="d-none" multiple="multiple" data-regex="image" data-max-mb-size=1
onchange="window.breakIntoSeparateFiles(this, '#image_uploads')">
</div>
</div>
</div>
Tiếp đến là dùng jquery để xử lý sự kiện upload hình ảnh.
// ______________upload image
var FILE_ICON_URL = 'https://icons.iconarchive.com/icons/zhoolego/material/512/Filetype-Docs-icon.png';
var MAX_MB_SIZE = 10;
function addFileToNewInput(file, newInput) {
if (!newInput) { return; }
var dataTransfer = new DataTransfer();
dataTransfer.items.add(file);
newInput.files = dataTransfer.files;
}
function addSrcToPreview(file, preview) {
if (!preview) { return; }
if (file.type.match(/image/)) {
var reader = new FileReader();
reader.onload = function (e) { preview.src = e.target.result; };
reader.readAsDataURL(file);
} else {
preview.src = FILE_ICON_URL;
}
}
function validateFile(file, options) {
if (options.regex && !file.type.match(new RegExp(options.regex))) {
return 'only ' + options.regex + ' type is allowed';
}
if (options.maxMbSize && file.size > (options.maxMbSize * 1024 * 1024)) {
return 'size bigger than ' + options.maxMbSize + 'MB';
}
return null;
}
function breakIntoSeparateFiles(input, targetSelector) {
var $input = $(input);
let name = $input.attr('name');
var options = $.extend({}, { maxMbSize: MAX_MB_SIZE }, $input.data());
if (!input.files) { return; }
for (var i = 0; i < input.files.length; i++) {
var file = input.files[i];
var errorMessage = validateFile(file, options);
var $newFile = $('<div class="files-box image_loaded">' +
'<div class="files-content">' +
'<img class="file-preview" src="' + FILE_ICON_URL + '">' +
'<span class="remove_file"><i class="fas fa-times-circle"></i></span>' +
//'<span class="remove_file" onclick="$(this).closest(\'.files-box\').remove();"><i class="fas fa-times-circle"></i></span>' +
'<input type="file" name="' + name + '" class="new-input" hidden>' +
/* '<span class="error-message">' + errorMessage + '</span>' + */
'</div>' +
'</div>').appendTo(targetSelector);
addFileToNewInput(file, $newFile.find(".new-input")[0]);
addSrcToPreview(file, $newFile.find(".file-preview")[0]);
}
$input.val([]);
}
window.breakIntoSeparateFiles = breakIntoSeparateFiles;
$('.files-area').on('click', '.remove_file', function () {
Swal.fire({
title: 'Are you sure you want to delete?',
text: "You won't be able to revert this!",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#d33',
cancelButtonColor: '#3085d6',
confirmButtonText: 'Yes, do it!'
}).then((result) => {
if (result.isConfirmed) {
$(this).closest('.files-box').remove();
}
});
});
Vậy là chúng ta đã có thể dễ dàng upload hình ảnh bằng sự hỗ trợ của spatie media library. Bạn hãy thoả sức biến hoá để có giao diện upload hình ảnh đẹp nhất cho ứng dụng laravel của bạn.