Lưu trữ tệp (OSS)
govex-cloud-oss cung cấp lớp lưu trữ file trừu tượng (Storage) thống nhất cho MinIO/S3, kèm REST API upload — xem/tải file hỗ trợ Range và cơ chế phân quyền truy cập file theo policy của ứng dụng.
Khi nào sử dụng
- Cần upload và quản lý file (ảnh, tài liệu PDF, logo...) mà không muốn phụ thuộc trực tiếp vào SDK của MinIO/S3.
- Cần endpoint xem/tải file cho frontend, có hỗ trợ tải từng phần (
Range) cho file lớn. - Cần kiểm soát quyền truy cập file private theo nghiệp vụ (chủ sở hữu, hồ sơ, phòng ban...).
Cài đặt
Thêm dependency vào pom.xml — không khai version vì đã được quản lý qua BOM:
<dependency>
<groupId>vn.govex.cloud</groupId>
<artifactId>govex-cloud-oss</artifactId>
</dependency>
Nếu ứng dụng chưa dùng parent/BOM của Govex Cloud, xem hướng dẫn tại Cài đặt.
Cấu hình
Cấu hình lưu trữ chỉ đọc từ application.yml với prefix govex.oss.*:
| Property | Mô tả | Mặc định |
|---|---|---|
govex.oss.enabled | Cho phép khởi tạo MinIO từ cấu hình govex.oss. | true |
govex.oss.url | Endpoint MinIO/S3. | — |
govex.oss.access-key / govex.oss.secret-key | Credential truy cập. | — |
govex.oss.bucket-name | Bucket chính. | — |
govex.oss.public-bucket-name | Bucket cho file công khai (MinIO). | — |
govex.oss.tmp-bucket-name | Bucket cho file tạm (MinIO). | Dùng lại bucket chính |
govex.oss.custom-domain | Domain tùy chỉnh để tạo URL file. | Dùng govex.oss.url |
govex.oss.region | Region (S3/MinIO). | — |
govex.oss.access.default-deny-when-no-policy | Từ chối file private khi không có policy nào xử lý path. | true |
Khi enabled=true và có đủ url, access-key, secret-key, bucket-name, bean storage khởi tạo MinIO. Nếu thiếu bất kỳ giá trị nào, dependency trả về null object (NoneStorage) và mọi thao tác file sẽ ném STORAGE_NOT_CONFIGURED.
Sử dụng
Cấu hình MinIO:
govex:
oss:
enabled: true
url: http://minio:9000
bucket-name: myapp
access-key: minioadmin
secret-key: minioadmin
Upload file qua Storage — caller chỉ làm việc với path opaque do upload() trả về:
@Service
@RequiredArgsConstructor
public class LogoService {
private final Storage storage;
public String uploadLogo(MultipartFile file) throws IOException {
return storage.upload(UploadRequest.builder()
.path("idp/logo")
.fileName(file.getOriginalFilename())
.inputStream(file.getInputStream())
.contentType(file.getContentType())
.accessLevel(AccessLevel.PUBLIC)
.build());
}
}
Các thao tác khác trên cùng path: stat (metadata), readBytes, openStream (có bản nhận offset/length để đọc từng phần), move, copy, delete, exists, isPublic. Muốn giữ chỗ đường dẫn trước khi upload (ví dụ tạo bản ghi trước, upload sau) dùng reservePath/uploadTo.
REST API sẵn có:
| Method | Endpoint | Mô tả |
|---|---|---|
POST | /api/v1/storage/upload | Upload multipart với các tham số file, access (public/private, mặc định private), path. |
GET | /api/v1/storage/file/** | Xem file; hỗ trợ header Range cho file private, cache 7 ngày cho file public. |
GET | /api/v1/storage/download/** | Tải file dạng attachment. |
GET | /api/v1/storage/view và /get | Endpoint cũ, đã deprecated — không dùng cho tích hợp mới. |
Phân quyền file private theo nghiệp vụ bằng cách khai báo FileAccessPolicy:
@Component
public class OwnerFileAccessPolicy implements FileAccessPolicy {
@Override
public boolean canAccess(String storagePath, Authentication authentication) {
return fileOwnerService.isOwner(storagePath, authentication.getName());
}
@Override
public boolean supports(String storagePath) {
return storagePath.startsWith("document/");
}
}
Lưu ý
- Cần hạ tầng MinIO/S3 sẵn sàng và cấu hình hợp lệ; nếu không có cấu hình, dependency vẫn nạp bình thường nhưng mọi thao tác file ném
STORAGE_NOT_CONFIGURED. - Upload qua REST chỉ chấp nhận JPEG, PNG, SVG, ICO và PDF; file không thuộc danh sách bị từ chối.
- File private bị từ chối mặc định khi không có
FileAccessPolicynào xử lý path (access.default-deny-when-no-policy=true). Cân nhắc đặtfalsenếu muốn mọi người dùng đã xác thực đều truy cập được, hoặc bổ sung policy phù hợp. - Ứng dụng có thể tự khai báo bean quản lý truy cập riêng; bean mặc định chỉ được tạo khi context chưa có bean tương ứng.