feat(uploads): add native resumable upload support

Implement a native chunked resumable upload API and frontend integration
to support reliable large file uploads.

Changes include:
- Added a 3-step resumable upload API flow (create session, upload chunks, complete session).
- Introduced configuration options for chunk size, retention hours, and toggling the feature.
- Updated the frontend to utilize resumable uploads with progress tracking.
- Configured temporary chunk storage under `data/tmp/uploads` with automatic cleanup.
- Documented the API flow and configuration in the README.
This commit is contained in:
2026-06-02 17:41:41 +03:00
parent d3b6a86753
commit 5cd476e7f3
16 changed files with 1805 additions and 85 deletions

View File

@@ -22,6 +22,14 @@ func newCleanupJob(cfg config.Config, logger *slog.Logger, uploadService *servic
if cleaned > 0 {
logger.Info("cleanup job complete", "source", "housekeeping", "severity", "user_activity", "code", 2202, "cleaned", cleaned)
}
cleanedUploads, err := uploadService.CleanupExpiredResumableSessions(time.Now().UTC())
if err != nil {
logger.Warn("resumable upload cleanup failed", "source", "housekeeping", "severity", "warn", "code", 4204, "error", err.Error())
return
}
if cleanedUploads > 0 {
logger.Info("resumable uploads cleaned", "source", "housekeeping", "severity", "user_activity", "code", 2204, "cleaned", cleanedUploads)
}
if banService != nil {
cleanedEvents, err := banService.CleanupAbuseEvents(time.Now().UTC())
if err != nil {
@@ -37,7 +45,12 @@ func newCleanupJob(cfg config.Config, logger *slog.Logger, uploadService *servic
}
func RunCleanupNow(uploadService *services.UploadService, logger *slog.Logger) (int, error) {
return cleanupUnavailableBoxes(uploadService, logger)
cleaned, err := cleanupUnavailableBoxes(uploadService, logger)
if err != nil {
return cleaned, err
}
cleanedUploads, err := uploadService.CleanupExpiredResumableSessions(time.Now().UTC())
return cleaned + cleanedUploads, err
}
func cleanupUnavailableBoxes(uploadService *services.UploadService, logger *slog.Logger) (int, error) {