File Uploads
16485

# File Uploads

Trong ứng dụng web, một trong những trường hợp sử dụng phổ biến nhất để lưu trữ tệp là lưu trữ các tệp được người dùng tải lên như hình ảnh và tài liệu. Laravel làm cho việc lưu trữ các files được upload rất dễ dàng bằng cách sử dụng phương thức store với tệp đã được upload. Gọi phương thức store với đường dẫn mà bạn muốn lưu trữ tệp được tải lên:

<?php
 
namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
 
class UserAvatarController extends Controller
{
    /**
     * Update the avatar for the user.
     */
    public function update(Request $request): string
    {
        $path = $request->file('avatar')->store('avatars');
 
        return $path;
    }
}

Có một số điều quan trọng cần lưu ý về ví dụ này. Lưu ý rằng chúng ta chỉ chỉ định tên thư mục, không phải tên tệp. Theo mặc định, phương thức store sẽ tạo ra một ID duy nhất để làm tên tệp. Phần mở rộng của tệp sẽ được xác định bằng cách kiểm tra loại MIME của tệp. Đường dẫn đến tệp sẽ được trả về bởi phương thức store để bạn có thể lưu trữ đường dẫn, bao gồm tên tệp được tạo ra, trong cơ sở dữ liệu của bạn. Bạn cũng có thể gọi phương thức putFile trên Storage facade để thực hiện cùng một hoạt động lưu trữ tệp như ví dụ trên:

$path = Storage::putFile('avatars', $request->file('avatar'));

# Chỉ định một tên tệp

Nếu bạn không muốn tự động gán tên tệp cho tệp đã lưu của mình, bạn có thể sử dụng phương thức storeAs, nhận đường dẫn, tên tệp và ổ đĩa (tùy chọn) là đối số của nó:

$path = $request->file('avatar')->storeAs(
    'avatars', $request->user()->id
);

Bạn cũng có thể sử dụng phương thức putFileAs trên Storage facade, sẽ thực hiện cùng một hoạt động lưu trữ tập tin như ví dụ trên:

$path = Storage::putFileAs(
    'avatars', $request->file('avatar'), $request->user()->id
);

# Chỉ định một ổ đĩa

Theo mặc định, phương thức lưu trữ của tệp tải lên này sẽ sử dụng ổ đĩa mặc định của bạn. Nếu bạn muốn chỉ định một ổ đĩa khác, hãy truyền tên ổ đĩa như là đối số thứ hai cho phương thức lưu trữ:

$path = $request->file('avatar')->store(
    'avatars/'.$request->user()->id, 's3'
);

// or
$path = $request->file('avatar')->storeAs(
    'avatars',
    $request->user()->id,
    's3'
);

# Thông tin file đã upload

// Lấy tên gốc của tập tin
$originalName = $file->getClientOriginalName();

// Lấy phần mở rộng của tập tin
$extension = $file->getClientOriginalExtension();

// Lấy kích thước của tập tin (đơn vị: byte)
$size = $file->getSize();

// Lấy MIME type của tập tin
$mimeType = $file->getMimeType();

// Lưu tập tin
$path = $file->store('uploads', 'public');

Tuy nhiên, hãy nhớ rằng các phương thức getClientOriginalName và getClientOriginalExtension được coi là không an toàn, vì tên tập tin và phần mở rộng có thể bị người dùng độc hại can thiệp. Vì lý do này, bạn nên thường chọn phương thức hashName và phần mở rộng để có được tên và phần mở rộng cho tệp tải lên cụ thể:

$file = $request->file('avatar');
 
$name = $file->hashName(); // Generate a unique, random name...
$extension = $file->extension(); // Determine the file's extension based on the file's MIME type...

# File Visibility

Trong tích hợp Flysystem của Laravel, "visibility" là một sự trừu tượng hóa của các quyền tập tin trên nhiều nền tảng khác nhau. Các tập tin có thể được khai báo là công khai (public) hoặc riêng tư (private). Khi một tập tin được khai báo là công khai, bạn đang chỉ định rằng tập tin đó thường nên được truy cập bởi những người khác. Ví dụ, khi sử dụng driver S3, bạn có thể lấy URL cho các tập tin công khai.

Thiết Lập Tính Năng Hiển Thị Tập Tin

Lưu Trữ Tập Tin Công Khai

Bạn có thể lưu trữ một tập tin và chỉ định nó là công khai như sau:

use Illuminate\Support\Facades\Storage;

$content = 'Nội dung của tập tin';
Storage::put('file.jpg', $content, 'public');

Nếu tập tin đã được lưu trữ, bạn có thể lấy và thiết lập tính năng hiển thị của nó thông qua các phương thức getVisibilitysetVisibility.

$visibility = Storage::getVisibility('file.jpg');

Storage::setVisibility('file.jpg', 'public');

Khi làm việc với các tập tin được tải lên, bạn có thể sử dụng các phương thức storePubliclystorePubliclyAs để lưu trữ tập tin với tính năng hiển thị công khai.

Phương Thức storePublicly

Phương thức storePublicly sẽ lưu trữ tập tin được tải lên với tính năng hiển thị công khai.

$path = $request->file('avatar')->storePublicly('avatars', 's3');

Phương Thức storePubliclyAs

Phương thức storePubliclyAs cho phép bạn chỉ định tên tập tin khi lưu trữ với tính năng hiển thị công khai.

$path = $request->file('avatar')->storePubliclyAs(
    'avatars',
    $request->user()->id,
    's3'
);

Tập Tin Cục Bộ và Tính Năng Hiển Thị

Khi sử dụng driver cục bộ (local), tính năng hiển thị công khai được dịch thành quyền 0755 cho thư mục và 0644 cho tập tin. Bạn có thể chỉnh sửa các phép ánh xạ quyền này trong tệp cấu hình filesystems của ứng dụng của bạn.

Cấu Hình filesystems.php

Trong tệp config/filesystems.php, bạn có thể cấu hình quyền truy cập cho driver cục bộ như sau:

'local' => [
    'driver' => 'local',
    'root' => storage_path('app'),
    'permissions' => [
        'file' => [
            'public' => 0644,
            'private' => 0600,
        ],
        'dir' => [
            'public' => 0755,
            'private' => 0700,
        ],
    ],
],

Giải Thích

  • Driver: local là driver cục bộ mà Laravel cung cấp để lưu trữ tập tin trên hệ thống tệp cục bộ.
  • Root: Đường dẫn gốc nơi các tập tin sẽ được lưu trữ. Mặc định là storage_path('app'), nghĩa là thư mục storage/app trong ứng dụng của bạn.
  • Permissions: Đây là nơi bạn có thể chỉ định quyền truy cập cho tập tin và thư mục dựa trên tính năng hiển thị của chúng.
    • File:
      • public (0644): Quyền truy cập công khai cho tập tin, cho phép chủ sở hữu có thể đọc và ghi, trong khi người dùng khác chỉ có thể đọc.
      • private (0600): Quyền truy cập riêng tư cho tập tin, chỉ cho phép chủ sở hữu có thể đọc và ghi.
    • Dir:
      • public (0755): Quyền truy cập công khai cho thư mục, cho phép chủ sở hữu có thể đọc, ghi và thực thi, trong khi người dùng khác chỉ có thể đọc và thực thi.
      • private (0700): Quyền truy cập riêng tư cho thư mục, chỉ cho phép chủ sở hữu có thể đọc, ghi và thực thi.

# Deleting Files

Trong Laravel, bạn có thể dễ dàng xóa các tập tin đã được lưu trữ bằng cách sử dụng các phương thức được cung cấp bởi Storage facade. Dưới đây là các phương pháp phổ biến để xóa tập tin trong Laravel.

Xóa Tập Tin Đơn Lẻ

Để xóa một tập tin đơn lẻ, bạn có thể sử dụng phương thức delete:

use Illuminate\Support\Facades\Storage;

Storage::delete('path/to/file.jpg');

Xóa Nhiều Tập Tin

Nếu bạn cần xóa nhiều tập tin cùng lúc, bạn có thể truyền một mảng các đường dẫn tập tin vào phương thức delete:

use Illuminate\Support\Facades\Storage;

Storage::delete([
    'path/to/file1.jpg',
    'path/to/file2.jpg',
    'path/to/file3.jpg'
]);

Kiểm Tra Tập Tin Trước Khi Xóa

Bạn có thể kiểm tra xem tập tin có tồn tại hay không trước khi xóa bằng cách sử dụng phương thức exists:

use Illuminate\Support\Facades\Storage;

if (Storage::exists('path/to/file.jpg')) {
    Storage::delete('path/to/file.jpg');
}

Xóa Tập Tin Cục Bộ

Nếu bạn đang làm việc với các tập tin cục bộ và muốn xóa chúng, bạn có thể sử dụng phương thức unlink của PHP. Tuy nhiên, sử dụng Storage facade của Laravel là cách tiếp cận tốt hơn vì nó trừu tượng hóa các chi tiết của hệ thống tập tin cơ bản:

use Illuminate\Support\Facades\Storage;

Storage::disk('local')->delete('path/to/file.jpg');

Xóa Thư Mục

Bạn có thể xóa cả một thư mục và tất cả các tập tin trong đó bằng phương thức deleteDirectory:

use Illuminate\Support\Facades\Storage;

Storage::deleteDirectory('path/to/directory');

Lấy Tất Cả Các Tập Tin Trong Một Thư Mục

Để lấy danh sách tất cả các tập tin trong một thư mục, bạn có thể sử dụng phương thức files của Storage facade:

use Illuminate\Support\Facades\Storage;

$files = Storage::files('path/to/directory');

Phương thức này sẽ trả về một mảng chứa các đường dẫn của tất cả các tập tin trong thư mục được chỉ định.

Lấy Tất Cả Các Tập Tin Kể Cả Trong Các Thư Mục Con

Nếu bạn muốn lấy tất cả các tập tin bao gồm cả trong các thư mục con, bạn có thể sử dụng phương thức allFiles:

use Illuminate\Support\Facades\Storage;

$allFiles = Storage::allFiles('path/to/directory');

Phương thức này sẽ trả về một mảng chứa các đường dẫn của tất cả các tập tin, kể cả trong các thư mục con của thư mục được chỉ định.

Lấy Tất Cả Các Thư Mục Con Trong Một Thư Mục

Để lấy danh sách tất cả các thư mục con trong một thư mục, bạn có thể sử dụng phương thức directories:

use Illuminate\Support\Facades\Storage;

$directories = Storage::directories('path/to/directory');

Phương thức này sẽ trả về một mảng chứa các đường dẫn của tất cả các thư mục con trong thư mục được chỉ định.

Lấy Tất Cả Các Thư Mục Con Bao Gồm Cả Trong Các Thư Mục Con Khác

Nếu bạn muốn lấy tất cả các thư mục con bao gồm cả trong các thư mục con khác, bạn có thể sử dụng phương thức allDirectories:

use Illuminate\Support\Facades\Storage;

$allDirectories = Storage::allDirectories('path/to/directory');

Phương thức này sẽ trả về một mảng chứa các đường dẫn của tất cả các thư mục con, kể cả trong các thư mục con khác của thư mục được chỉ định.

Tạo Một Thư Mục

Để tạo một thư mục mới, bạn có thể sử dụng phương thức makeDirectory:

use Illuminate\Support\Facades\Storage;

Storage::makeDirectory('path/to/directory');

-----------------------------------------------------------------------------------------------------------------------------------------

# Example:

Trước khi bắt đầu, hãy chắc chắn rằng thư mục lưu trữ tập tin tải lên có quyền ghi. Thư mục mặc định là storage/app/public.

Tạo symbolic link: Chạy lệnh sau để tạo một symbolic link từ public/storage tới storage/app/public:

php artisan storage:link

Tạo Form Để Tải Lên Tập Tin

Đầu tiên, bạn cần tạo một form để người dùng có thể chọn tập tin để tải lên.

Ví Dụ Form Trong Blade:
<form action="{{ route('upload') }}" method="POST" enctype="multipart/form-data">
    @csrf
    <div>
        <label for="file">Choose file</label>
        <input type="file" id="file" name="file">
        @error('file')
            <div class="error">{{ $message }}</div>
        @enderror
    </div>
    <button type="submit">Upload</button>
</form>

Lưu ý rằng bạn cần sử dụng enctype="multipart/form-data" trong thẻ <form> để có thể tải lên tập tin.

Xử Lý Yêu Cầu Tải Lên Trong Controller

Tiếp theo, tạo một phương thức trong controller để xử lý việc tải lên tập tin.

Ví Dụ Trong Controller:
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;

class FileUploadController extends Controller
{
    public function upload(Request $request)
    {
        // Kiểm tra dữ liệu
        $request->validate([
            'file' => 'required|file|mimes:jpg,png,pdf|max:2048',
        ]);

        // Lưu tập tin
        if ($request->file('file')->isValid()) {
            $path = $request->file('file')->store('uploads', 'public');

            return back()->with('success', 'File uploaded successfully.')->with('file', $path);
        }

        return back()->with('error', 'There was an error uploading your file.');
    }
}

Cấu Hình Route

Cuối cùng, cấu hình route để xử lý form upload.

Ví Dụ Trong web.php:
use App\Http\Controllers\FileUploadController;

Route::get('/upload', function () {
    return view('upload');
})->name('upload.form');

Route::post('/upload', [FileUploadController::class, 'upload'])->name('upload');

Danh mục


  1. Khác
  2. ThreeJS
  3. Ubuntu/Linux
  4. HTML/CSS
  5. Git
  6. Amazon Web Services
  7. Javascript
  8. Docker
  9. Laravel

Bài viết liên quan


Routing

Routing

01.08.2024
Author: ADMIN
Hướng dẫn chi tiết về Basic Routing trong Laravel, từ cách định nghĩa route, sử dụng middleware, route caching đến route naming giúp tối ưu hóa ứng dụng.
Blade Basics

Blade Basics

01.08.2024
Author: ADMIN
Khám phá Blade trong Laravel: từ if-else, loops, kế thừa layout đến include sub-views. Giúp code gọn gàng, dễ quản lý và bảo trì hơn!
Hiển thị giá trị trong Blade

Hiển thị giá trị trong Blade

01.08.2024
Author: ADMIN
Hướng dẫn hiển thị biến trong Laravel Blade: escape HTML tự động, hiển thị dữ liệu thô, giá trị mặc định và cách truy xuất mảng, đối tượng. Giúp bạn tối ưu hiển thị dữ liệu một cách an toàn!
Layout: @include, @extends, @section, @yield

Layout: @include, @extends, @section, @yield

01.08.2024
Author: ADMIN
Hướng dẫn chi tiết về @include, @extends, @section và @yield trong Laravel Blade. Tối ưu hóa tái sử dụng giao diện, tổ chức mã rõ ràng, giúp phát triển và bảo trì ứng dụng dễ dàng hơn!

Bài viết khác

Routing

Routing

01.08.2024
Author: ADMIN
Hướng dẫn chi tiết về Basic Routing trong Laravel, từ cách định nghĩa route, sử dụng middleware, route caching đến route naming giúp tối ưu hóa ứng dụng.
Blade Basics

Blade Basics

01.08.2024
Author: ADMIN
Khám phá Blade trong Laravel: từ if-else, loops, kế thừa layout đến include sub-views. Giúp code gọn gàng, dễ quản lý và bảo trì hơn!
9 Mẹo Hữu Ích Khi Sử Dụng Blade Trong Laravel

9 Mẹo Hữu Ích Khi Sử Dụng Blade Trong Laravel

01.08.2024
Author: ADMIN
Khám phá 9 mẹo Blade giúp bạn viết code Laravel sạch, tối ưu và chuyên nghiệp hơn. Từ @forelse, @auth, @guest, đến format ngày, tối ưu SEO – tất cả trong một bài viết súc tích, dễ áp dụng!
Hiển thị giá trị trong Blade

Hiển thị giá trị trong Blade

01.08.2024
Author: ADMIN
Hướng dẫn hiển thị biến trong Laravel Blade: escape HTML tự động, hiển thị dữ liệu thô, giá trị mặc định và cách truy xuất mảng, đối tượng. Giúp bạn tối ưu hiển thị dữ liệu một cách an toàn!