Làm sao để upload tệp lên S3 Bucket của Amazon

Amazon web services đã không còn xa lạ gì với chúng ta khi làm lập trình web nói riêng cũng như lập trình úng dụng nói chung. Ở bài viết này tôi sẽ hướng dẫn các bạn tải file lên s3 bucket amazon sử dụng framework Laravel. Tôi sẽ dùng Laravel 8 sẽ có 1 số thay đổi so với bản cũ trước đây như bản 6, 5.

Để có thể tải lên thì các bạn cần có s3 bucket, bài viết này cũng sẽ hướng dẫn các bạn tạo s3 bucket của riêng mình.

Bước 1: Tạo s3 Bucket

  1. Đi đến Amazon Web Service Console và đăng nhập tài khoản
  2. Chọn vào S3 ở list Servies
  3. Chọn "Create Bucket" và bạn sẽ thấy form dưới đây, bạn có thể điền tên bucket của mình ở đó.
  4. Tạo IAM User. Chọn vào đây để tạo
  5. Chọn vào nút "Create User" như dưới đây.
  6. Tiếp theo thêm Username dùng và chọn "Programmatic access" từ "access type". sau đó nhấp vào tiếp theo.
  7. Tiếp theo Chọn “Attach Existing Policy Directly” và chọn “AmazonS3FullAccess” từ liên kết quyền.
  8. Bạn có thể bỏ qua và nhấp vào tiếp theo ở bước tiếp theo.
  9. Bạn có thể xem chi tiết người dùng và sau đó nhấp vào nút "Create User".
  10. Bây giờ bạn sẽ thấy người dùng đã tạo trong liên kết. có "Access Key ID" và "Secret Access Key" mà tôi cần trên tệp .env.

Bước 2: Cài đặt Laravel 8

Các bạn có thể tạo trước dự án Laravel và bỏ qua bước này nhưng ở đây tôi sẽ hướng dẫn từng bước nên tôi sẽ tạo mới 1 dự án. Để tạo các bạn chạy câu lệnh:
composer create-project --prefer-dist laravel/laravel blog

Bước 3: Cài đặt Amazon S3 Composer Package

Nếu bạn chưa cài đặt gói s3 amazon thì bạn phải cài đặt gói s3 composer bằng cách sử dụng lệnh sau:
composer require --with-all-dependencies league/flysystem-aws-s3-v3 "^1.0"

Bước 4: Configure AWS S3 Credentials trong .env

Bây giờ bạn cần thêm thông tin đăng nhập aws vào tệp .env của mình như sau:
.env

AWS_ACCESS_KEY_ID=AKIAVAEWWDTDY...
AWS_SECRET_ACCESS_KEY=Zp/wgwj46SAC....
AWS_DEFAULT_REGION=us-east-2
AWS_BUCKET=itsolutionstuff-bucket
AWS_USE_PATH_STYLE_ENDPOINT=false

Bước 5: Tạo route để có thể lấy file và tải lên s3

Bước tiếp theo tôi sẽ tạo 2 route mới ở file web.php. Một route để lấy nội dung của file và một route để tải nó lên s3:
routes/web.php

<?php
  
use Illuminate\Support\Facades\Route;
  
use App\Http\Controllers\ImageUploadController;
  
  
Route::get('image-upload', [ ImageUploadController::class, 'imageUpload' ])->name('image.upload');
Route::post('image-upload', [ ImageUploadController::class, 'imageUploadPost' ])->name('image.upload.post');

Bước 6: Tạo controller ImageUpload

Ở đây sẽ tạo ra 1 controller mới là ImageUpload và nó sẽ bao gôm 2 phương thức mageUpload() và imageUploadPost(). Một phương thức sẽ xử lý lấy nội dung file, một phương thức xử lý tải ảnh lên s3:

app/Http/Controllers/ImageUploadController.php

<?php
  
namespace App\Http\Controllers;
  
use Illuminate\Http\Request;
  
class ImageUploadController extends Controller
{
     /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function imageUpload()
    {
        return view('imageUpload');
    }
    
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function imageUploadPost(Request $request)
    {
        $request->validate([
            'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
        ]);
    
        $imageName = time().'.'.$request->image->extension();  
     
        $path = Storage::disk('s3')->put('images', $request->image);
        $path = Storage::disk('s3')->url($path);
  
        /* Store $imageName name in DATABASE from HERE */
    
        return back()
            ->with('success','You have successfully upload image.')
            ->with('image', $path); 
    }
}

Bước 7: Tạo blade bao gồm form tải

Bước cuối cùng, chúng ta cần tạo tệp image_upload.blade.php và trong này chúng ta phải tạo form để có thể nhập tệp vào:

resources/views/image_upload.blade.php

<!DOCTYPE html>
<html>
<head>
    <title>laravel File Uploading with Amazon S3 - ItSolutionStuff.com.com</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
</head>
    
<body>
<div class="container">
     
    <div class="panel panel-primary">
      <div class="panel-heading"><h2>laravel File Uploading with Amazon S3 - ItSolutionStuff.com.com</h2></div>
      <div class="panel-body">
     
        @if ($message = Session::get('success'))
        <div class="alert alert-success alert-block">
            <button type="button" class="close" data-dismiss="alert">×</button>
                <strong>{{ $message }}</strong>
        </div>
        <img src="{{ Session::get('image') }}">
        @endif
    
        @if (count($errors) > 0)
            <div class="alert alert-danger">
                <strong>Whoops!</strong> There were some problems with your input.
                <ul>
                    @foreach ($errors->all() as $error)
                        <li>{{ $error }}</li>
                    @endforeach
                </ul>
            </div>
        @endif
    
        <form action="{{ route('image.upload.post') }}" method="POST" enctype="multipart/form-data">
            @csrf
            <div class="row">
    
                <div class="col-md-6">
                    <input type="file" name="image" class="form-control">
                </div>
     
                <div class="col-md-6">
                    <button type="submit" class="btn btn-success">Upload</button>
                </div>
     
            </div>
        </form>
    
      </div>
    </div>
</div>
</body>
  
</html>

Bây giờ bạn có thể chạy và kiểm tra lại những gì đã làm.
Cảm ơn bạn đã đọc đến đây, chúc các bạn sẽ có những ngày làm việc bùng nổ ^^