Trang chủ Kiến Thức Công Nghệ Upload File từ Frontend đến Backend mà rất nhiều bạn vẫn đang làm sai!!
Công Nghệ

Upload File từ Frontend đến Backend mà rất nhiều bạn vẫn đang làm sai!!

Chia sẻ
Upload File từ Frontend đến Backend mà rất nhiều bạn vẫn đang làm sai!!
Chia sẻ

1. Client encode file (base64) rồi gởi về backend

200Lab đã từng thấy nhiều bạn backend developer yêu cầu phía frontend làm như vậy. Cách này nhược điểm là xử lý rất nặng ở cả 2 phía. Vì frontend phải encode mà backend cũng phải decode.

200Lab đã từng thấy nhiều bạn backend developer yêu cầu phía

Trong cách này nếu backend không decode để tái tạo lại file mà lưu hết base64 string vào DB sẽ là một sai lầm rất nghiêm trọng. Khi ấy DB chúng ta rất nặng vì chứa cả file vật lý. Khi truy xuất tốn CPU và băng thông rất lớn.

=> Rõ ràng đây không phải là một giải pháp tốt.

2. Client(Front-end) dùng API + Secret Key để thực hiện upload trực tiếp lên các Cloud Storage

Đây là một giải pháp nhanh gọn, đỡ phải qua backend, NHƯNG cực kì tệ. Lý do rất đơn giản là vì secret key dễ dàng bị leak chỉ với một thủ pháp đơn giản là… capture/debug request upload file.

Một khi secret key bị lộ, người tấn công có thể toàn quyền với key ấy. Nhẹ thì storage của chúng ta bị xài free. Nặng thì bị kéo toàn bộ file hoặc xoá toàn bộ file trên storage (nếu key có quyền xoá).

Nếu vậy thì làm sao cho ĐÚNG? Có 2 cách các bạn có thể tham khảo:

Cách 1: Upload trung gian qua backend:

Client upload file lên backend nhưng không cần thực hiện base64 encode. Chúng ta chỉ cần sử dụng multipart form data là ổn. Khi ấy backend nhận file xong có thể lựa chọn upload tiếp lên Cloud Storage hoặc một nơi nào đó bảo mật mà chỉ có backend biết.

Như vậy client không cần secret key nên không sợ lộ nữa. Backend khi cần có thể chuyển đổi được dịch vụ Cloud nhanh chóng.Tuy nhiên cách này có nhược điểm:

  • Client sẽ đợi lâu hơn đáng kể để nhận phản hồi từ backend. Vì backend phải upload lại qua Cloud.
  • Băng thông tiêu thụ ở backend sẽ gấp đôi. VD nhận file 10MB, upload đi 10MB là 20MB băng thông I/O.

Cách 2: Client upload file lên Cloud Storage NHƯNG dùng Presigned URL từ backend:

Để giải quyết tốt hơn cho bài toán trên, các nhà điều hành Cloud Storage đã nghĩ ra một giải pháp để vừa có thể đảm bảo tính bảo mật và backend cũng không cần tốn băng thông. Đó là Presigned URL.

Presigned URL đại khái là một URL với các thông số bảo mật, cung cấp một permission tạm thời để đọc và tạo file trên Cloud. Để tạo thành công Presigned URL, chúng ta cần backend làm điều này. Một lần nữa, 200Lab nhấn mạnh và khuyên rằng chúng ta không nên làm việc này ở Client/Frontend.

Cách implement API upload này khá đơn giản, các bạn có thể viết một API GET trả về một đường link đặc biệt (Presigned URL). Client sử dụng link này để upload file lên (hay đúng hơn là PUT Object lên S3).

VD cách lấy Presigned URL với Golang:

Go

package main

import (
    "github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/s3"
    "log"
    "time"
)

func main() {
    sess, err := session.NewSession(&aws.Config{
        Region: aws.String("your bucket region")},
        Credentials: credentials.NewStaticCredentials(
			"your api key", // Access key ID
			"your secret key", // Secret access key
			"token (optional)",
        )
    )

    // Create S3 service client
    svc := s3.New(sess)

    req, _ := svc.PutObjectRequest(&s3.GetObjectInput{
        Bucket: aws.String("myBucket"),
        Key:    aws.String("myFileName"),
    })
    urlStr, err := req.Presign(5 * time.Minute)

    if err != nil {
        log.Println("Failed to sign request", err)
    }

    log.Println("The URL is", urlStr)
}
Presigned URL có hạn sử dụng trong 5 phút

Còn với NodeJS thì đại khái như sau:

JS

var req = require('request');
var fs = require('fs');
var AWS = require('aws-sdk');

AWS.config.update({
  accessKeyId: "your api key",
  secretAccessKey: "your secret key"
});

var s3 = new AWS.S3();
var params = {Bucket: 'bucket-name', Key: 'myFileName', Expires: 5 * 60 };
var url = s3.getSignedUrl('putObject', params);

console.log(url);

Client có thể dùng URL này để upload file trực tiếp vào (method PUT với body file content cần upload). Như vậy backend không cần phải “trung chuyển” file nữa. Từ đó vấn đề băng thông được giải quyết. Resource được giải phóng. Hoá đơn tính tiền cũng nhẹ gánh rất đáng kể.

Tóm lại:

Hy vọng rằng với chia sẻ trên, các bạn Backend sẽ làm API Upload file chuẩn chỉnh hơn.

Bên cạnh đó giải pháp này cũng thường được dùng để download file (GET Object S3) với một URL có hiệu lực tạm thời, và cũng chính là PresignedURL. Với cách này, hy vọng các bạn đã có thể tăng bảo mật cho S3 của mình nhé :D.

Chia sẻ

Để lại bình luận

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

Bài viết cùng chuyên mục
Tối ưu ứng dụng với cấu trúc dữ liệu cơ bản và bitwise
Công Nghệ

Tối ưu ứng dụng với cấu trúc dữ liệu cơ bản và bitwise

Trong bài viết này, 200Lab sẽ chia sẻ những trường hợp dễ...

Công Nghệ

So sánh Flutter vs React Native: Framework nào đáng học năm 2021

Điểm chung của Flutter, React Native đều là Cross-platform Mobile, build native...

HTTP/2 là gì? So sánh HTTP/2 và HTTP/1
Công Nghệ

HTTP/2 là gì? So sánh HTTP/2 và HTTP/1

Từ khi Internet ra đời, sự phát triển về các giao thức...

Công Nghệ

React Native – Hướng dẫn làm việc với Polyline và Animated-Polyline trên Map

Vẽ đường đi trên bản đồ là một nghiệp vụ vô cùng...

Công Nghệ

Hybrid App và Native App: Những khác biệt to lớn

Bất cứ khi nào một công ty quyết định làm ứng dụng...

Web/System Architecture 101 – Kiến trúc web/hệ thống cơ bản cho người mới
Công Nghệ

Web/System Architecture 101 – Kiến trúc web/hệ thống cơ bản cho người mới

Đây là một kiến trúc cơ bản mà bất kì một người...

Công Nghệ

Tư duy kiến trúc thông qua các trò chơi mà rất nhiều bạn không biết

Tư duy kiến trúc là gì? Tư duy kiến trúc có thể...

HTTP/3 là gì – Giao thức đột phá để tăng tải website
Công Nghệ

HTTP/3 là gì – Giao thức đột phá để tăng tải website

Nhắc lại một chút về HTTP/2 ở bài trước, từ khi giao...

Chiến lược leo lương: >= 1000$ NET (thậm chí > 3000$ NET)
Công Nghệ

Chiến lược leo lương: >= 1000$ NET (thậm chí > 3000$ NET)

Một ngàn đô Mỹ (1000$) là mức lương thường thấy cho vị...

Công Nghệ

Flutter vs React Native: Lựa chọn nào tốt nhất hiện nay

Flutter vs React Native? Có bao giờ bạn thắc mắc liệu sử...

Digital Ocean: Hướng dẫn tạo Droplet cùng 100$ FREE credit
Công Nghệ

Digital Ocean: Hướng dẫn tạo Droplet cùng 100$ FREE credit

Nếu bạn đang là người học lập trình, đặc biệt về backend,...

Công Nghệ

4 nguồn thu nhập thụ động dễ dàng cho lập trình viên

Cơ hội kiếm từ $ 500 đến $ 50.000 mỗi tháng Ai...