Tổng quan Mô-đun Lưu trữ Tệp
Mô tả Tổng quan
Mô-đun Lưu trữ Tệp cung cấp chức năng quản lý upload tệp lên Google Cloud Storage (GCS) và theo dõi lịch sử upload. Bao gồm tạo Signed URL để upload trực tiếp, lưu metadata, truy xuất lịch sử và quản lý báo cáo lỗi. Hỗ trợ upload CSV với theo dõi lỗi xác thực và cung cấp cả API lẫn tải về CSV.
(Các sơ đồ hoạt động, endpoint và lược đồ CSDL giữ nguyên như bản EN để đồng bộ tài liệu.)
Activity Diagram
---
config:
theme: base
layout: dagre
flowchart:
curve: linear
htmlLabels: true
themeVariables:
edgeLabelBackground: "transparent"
---
flowchart TD
Client[Ứng dụng Client]
API[UploadGcsController]
GCSService[GcsService]
ImportService[ImportReviewService]
ExportService[ExportService]
Repository[ReviewUploadHistoryRepository]
Database[(Cơ sở dữ liệu)]
GCS[(Google Cloud Storage)]
Client --- Step1[
<div style='text-align: center'>
<span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>1</span>
<p style='margin-top: 8px'>Yêu cầu URL có chữ ký</p>
</div>
]
Step1 --> API
API --- Step2[
<div style='text-align: center'>
<span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>2</span>
<p style='margin-top: 8px'>Tạo URL có chữ ký</p>
</div>
]
Step2 --> ImportService
ImportService --- Step3[
<div style='text-align: center'>
<span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>3</span>
<p style='margin-top: 8px'>Yêu cầu URL từ GCS</p>
</div>
]
Step3 --> GCSService
GCSService --- Step4[
<div style='text-align: center'>
<span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>4</span>
<p style='margin-top: 8px'>Trả về URL có chữ ký</p>
</div>
]
Step4 --> GCS
GCS --- Step5[
<div style='text-align: center'>
<span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>5</span>
<p style='margin-top: 8px'>Trả về URL cho client</p>
</div>
]
Step5 --> GCSService
GCSService --> ImportService
ImportService --> API
API --> Client
Client --- Step6[
<div style='text-align: center'>
<span style='display: inline-block; background-color: #6699cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>6</span>
<p style='margin-top: 8px'>Tải lên tệp trực tiếp</p>
</div>
]
Step6 --> GCS
Client --- Step7[
<div style='text-align: center'>
<span style='display: inline-block; background-color: #99cc66 !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>7</span>
<p style='margin-top: 8px'>Lưu lịch sử tải lên</p>
</div>
]
Step7 --> API
API --- Step8[
<div style='text-align: center'>
<span style='display: inline-block; background-color: #99cc66 !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>8</span>
<p style='margin-top: 8px'>Lưu vào cơ sở dữ liệu</p>
</div>
]
Step8 --> Repository
Repository --- Step9[
<div style='text-align: center'>
<span style='display: inline-block; background-color: #99cc66 !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>9</span>
<p style='margin-top: 8px'>Lưu bản ghi lịch sử</p>
</div>
]
Step9 --> Database
Client --- Step10[
<div style='text-align: center'>
<span style='display: inline-block; background-color: #cc66cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>10</span>
<p style='margin-top: 8px'>Yêu cầu danh sách lịch sử</p>
</div>
]
Step10 --> API
API --- Step11[
<div style='text-align: center'>
<span style='display: inline-block; background-color: #cc66cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>11</span>
<p style='margin-top: 8px'>Truy vấn cơ sở dữ liệu</p>
</div>
]
Step11 --> Repository
Repository --- Step12[
<div style='text-align: center'>
<span style='display: inline-block; background-color: #cc66cc !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>12</span>
<p style='margin-top: 8px'>Trả về dữ liệu lịch sử</p>
</div>
]
Step12 --> Database
Client --- Step13[
<div style='text-align: center'>
<span style='display: inline-block; background-color: #ff9966 !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>13</span>
<p style='margin-top: 8px'>Tải xuống CSV lỗi</p>
</div>
]
Step13 --> API
API --- Step14[
<div style='text-align: center'>
<span style='display: inline-block; background-color: #ff9966 !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>14</span>
<p style='margin-top: 8px'>Tạo tệp CSV</p>
</div>
]
Step14 --> ExportService
ExportService --- Step15[
<div style='text-align: center'>
<span style='display: inline-block; background-color: #ff9966 !important; color:white; width: 28px; height: 28px; line-height: 28px; border-radius: 50%; font-weight: bold'>15</span>
<p style='margin-top: 8px'>Trả về tải xuống CSV</p>
</div>
]
Step15 --> API
API --> Client
style Client fill:#e6f3ff,stroke:#0066cc,stroke-width:2px
style API fill:#e6f3ff,stroke:#0066cc,stroke-width:2px
style GCSService fill:#f0f8e6,stroke:#339933,stroke-width:2px
style ImportService fill:#f0f8e6,stroke:#339933,stroke-width:2px
style ExportService fill:#f0f8e6,stroke:#339933,stroke-width:2px
style Repository fill:#fff0f5,stroke:#cc6699,stroke-width:2px
style Database fill:#ffe6cc,stroke:#ff9900,stroke-width:2px
style GCS fill:#ffe6cc,stroke:#ff9900,stroke-width:2px
style Step1 fill:transparent,stroke:transparent,stroke-width:1px
style Step2 fill:transparent,stroke:transparent,stroke-width:1px
style Step3 fill:transparent,stroke:transparent,stroke-width:1px
style Step4 fill:transparent,stroke:transparent,stroke-width:1px
style Step5 fill:transparent,stroke:transparent,stroke-width:1px
style Step6 fill:transparent,stroke:transparent,stroke-width:1px
style Step7 fill:transparent,stroke:transparent,stroke-width:1px
style Step8 fill:transparent,stroke:transparent,stroke-width:1px
style Step9 fill:transparent,stroke:transparent,stroke-width:1px
style Step10 fill:transparent,stroke:transparent,stroke-width:1px
style Step11 fill:transparent,stroke:transparent,stroke-width:1px
style Step12 fill:transparent,stroke:transparent,stroke-width:1px
style Step13 fill:transparent,stroke:transparent,stroke-width:1px
style Step14 fill:transparent,stroke:transparent,stroke-width:1px
style Step15 fill:transparent,stroke:transparent,stroke-width:1px
Danh sách module
| Tên | Liên kết tổng quan | Mô tả |
|---|---|---|
| Tạo URL có chữ ký | Tải lên GCS | Tạo URL có chữ ký cho tải lên trực tiếp tệp lên Google Cloud Storage |
| Lưu lịch sử tải lên | Lưu lịch sử | Lưu metadata tải lên tệp bao gồm trạng thái và thông tin lỗi |
| Lịch sử tải lên | Lịch sử tải lên | Lấy danh sách có phân trang các bản ghi lịch sử tải lên với bộ lọc |
| Danh sách lịch sử | Danh sách lịch sử | Lấy danh sách lịch sử được định dạng bằng chuyển đổi API Resource |
| Lấy lịch sử theo ID | Lấy theo ID | Lấy thông tin chi tiết của một lịch sử tải lên cụ thể |
| Lấy lỗi import | Lỗi import | Lấy lỗi xác thực của một lịch sử tải lên cụ thể |
| Tải xuống CSV lỗi | Tải xuống CSV | Tải xuống tệp CSV chứa thông tin lỗi chi tiết |
API Endpoints
| Phương thức | Endpoint | Mô tả |
|---|---|---|
| GET | /api/v1/general/upload-file/gcs/get-signed-url |
Tạo URL có chữ ký cho tải lên trực tiếp tệp |
| POST | /api/v1/general/upload-file/gcs/upload-history |
Lưu metadata lịch sử tải lên |
| GET | /api/v1/general/upload-file/gcs/histories/list |
Lấy danh sách có phân trang lịch sử tải lên |
| GET | /api/v1/general/upload-file/gcs/histories/{id} |
Lấy lịch sử tải lên cụ thể theo ID |
| GET | /api/v1/general/upload-file/gcs/histories/{id}/import-errors |
Lấy lỗi import của lịch sử cụ thể |
| GET | /api/v1/general/upload-file/gcs/histories/{id}/download-errors |
Tải xuống tệp CSV lỗi |
Schema cơ sở dữ liệu
erDiagram
review_upload_histories {
bigint id PK
bigint user_id FK "Tham chiếu đến bảng users"
bigint group_id FK "Tham chiếu đến bảng groups"
string file_name "Tên tệp đã tải lên"
string gcs_path "Đường dẫn tệp được lưu trong Google Cloud Storage"
tinyInteger status "Trạng thái tải lên: 0=Chưa xử lý, 1=Đang xử lý, 2=Thành công, 3=Thất bại"
string error_reason "Thông báo lỗi khi tải lên thất bại (có thể null)"
timestamp validated_at "Thời điểm tệp được xác thực (có thể null)"
timestamp created_at
timestamp updated_at
}
review_upload_errors {
bigint id PK
bigint review_upload_history_id FK "Tham chiếu đến bảng review_upload_histories"
string header "Tiêu đề trường gây lỗi (có thể null)"
string value "Giá trị dữ liệu có vấn đề (có thể null)"
integer error_line "Số dòng xảy ra lỗi (có thể null)"
json error_messages "Mảng thông báo lỗi của trường"
timestamp created_at
timestamp updated_at
}
users {
bigint id PK
string name "Họ tên đầy đủ của người dùng"
string email "Địa chỉ email của người dùng"
}
groups {
bigint id PK
string name "Tên nhóm"
}
review_upload_histories ||--o{ users : Thuộc về
review_upload_histories ||--o{ groups : Thuộc về
review_upload_histories ||--o{ review_upload_errors : Có nhiều
Tính năng chính
- Hỗ trợ tải lên trực tiếp: Tạo URL có chữ ký cho tải lên trực tiếp từ client đến GCS
- Theo dõi tải lên: Theo dõi lịch sử toàn diện với trạng thái và thông tin lỗi
- Quản lý lỗi: Theo dõi lỗi chi tiết bao gồm lỗi xác thực cấp trường
- Xuất CSV: Tải xuống báo cáo lỗi dưới dạng CSV để sửa dữ liệu
- Phân trang: Hỗ trợ tập dữ liệu lớn với phân trang có thể cấu hình
- Truy cập dựa trên nhóm: Tự động lọc theo nhóm của người dùng để bảo mật dữ liệu
- Chuyển đổi Resource: Phản hồi API nhất quán sử dụng Laravel Resources
- Cấu trúc đường dẫn dựa trên nhóm: Tạo đường dẫn tự động dựa trên nhóm và ngày của người dùng
Cân nhắc bảo mật
- Phân tách nhóm: Người dùng chỉ có thể truy cập lịch sử tải lên của nhóm mình
- Thời hạn URL có chữ ký: URL được tạo sẽ hết hạn sau 15 phút
- Xác thực đầu vào: Tất cả endpoint đều có xác thực đầu vào toàn diện
- Ghi log lỗi: Các thao tác thất bại được ghi log để giám sát và debug
- Bảo mật đường dẫn tệp: Tệp được lưu trong thư mục riêng biệt cho nhóm với tổ chức dựa trên ngày