Implement resumable chunked uploads to improve reliability for large file
uploads that may fail due to network issues or timeouts.
New API endpoints:
- POST /repos/{owner}/{repo}/releases/{id}/assets/upload-session
- PUT /repos/{owner}/{repo}/uploads/{session_id}/chunks/{chunk_number}
- GET /repos/{owner}/{repo}/uploads/{session_id}
- POST /repos/{owner}/{repo}/uploads/{session_id}/complete
- DELETE /repos/{owner}/{repo}/uploads/{session_id}
Features:
- Resumable uploads with session status tracking
- Out-of-order chunk uploads supported
- Configurable chunk size (default 10MB, max 100MB)
- Automatic cleanup of expired sessions (24h expiry, hourly cleanup)
- Progress tracking with bytes/chunks received counts
Files added:
- models/repo/upload_session.go - Session model and DB operations
- services/attachment/chunked.go - Chunk storage and assembly logic
- routers/api/v1/repo/upload.go - API endpoint handlers
- models/migrations/v1_26/v325.go - Database migration
91 lines
3.4 KiB
Go
91 lines
3.4 KiB
Go
// Copyright 2017 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package structs // import "code.gitea.io/gitea/modules/structs"
|
|
|
|
import (
|
|
"time"
|
|
)
|
|
|
|
// Attachment a generic attachment
|
|
// swagger:model
|
|
type Attachment struct {
|
|
// ID is the unique identifier for the attachment
|
|
ID int64 `json:"id"`
|
|
// Name is the filename of the attachment
|
|
Name string `json:"name"`
|
|
// Size is the file size in bytes
|
|
Size int64 `json:"size"`
|
|
// DownloadCount is the number of times the attachment has been downloaded
|
|
DownloadCount int64 `json:"download_count"`
|
|
// swagger:strfmt date-time
|
|
// Created is the time when the attachment was uploaded
|
|
Created time.Time `json:"created_at"`
|
|
// UUID is the unique identifier for the attachment file
|
|
UUID string `json:"uuid"`
|
|
// DownloadURL is the URL to download the attachment
|
|
DownloadURL string `json:"browser_download_url"`
|
|
}
|
|
|
|
// EditAttachmentOptions options for editing attachments
|
|
// swagger:model
|
|
type EditAttachmentOptions struct {
|
|
// Name is the new filename for the attachment
|
|
Name string `json:"name"`
|
|
}
|
|
|
|
// UploadSessionResponse response for creating an upload session
|
|
// swagger:model
|
|
type UploadSessionResponse struct {
|
|
// UUID is the unique identifier for this upload session
|
|
UUID string `json:"uuid"`
|
|
// FileName is the name of the file being uploaded
|
|
FileName string `json:"file_name"`
|
|
// FileSize is the total size of the file in bytes (-1 if unknown)
|
|
FileSize int64 `json:"file_size"`
|
|
// ChunkSize is the size of each chunk in bytes
|
|
ChunkSize int64 `json:"chunk_size"`
|
|
// ChunksExpected is the expected number of chunks (-1 if unknown)
|
|
ChunksExpected int64 `json:"chunks_expected"`
|
|
// ExpiresAt is the Unix timestamp when this session expires
|
|
ExpiresAt int64 `json:"expires_at"`
|
|
}
|
|
|
|
// UploadChunkResponse response after uploading a chunk
|
|
// swagger:model
|
|
type UploadChunkResponse struct {
|
|
// ChunkNumber is the number of the chunk that was uploaded
|
|
ChunkNumber int64 `json:"chunk_number"`
|
|
// ChunksReceived is the total number of chunks received so far
|
|
ChunksReceived int64 `json:"chunks_received"`
|
|
// BytesReceived is the total number of bytes received so far
|
|
BytesReceived int64 `json:"bytes_received"`
|
|
// Complete indicates whether all chunks have been received
|
|
Complete bool `json:"complete"`
|
|
}
|
|
|
|
// UploadSessionInfo contains information about an upload session for resuming
|
|
// swagger:model
|
|
type UploadSessionInfo struct {
|
|
// UUID is the unique identifier for this upload session
|
|
UUID string `json:"uuid"`
|
|
// FileName is the name of the file being uploaded
|
|
FileName string `json:"file_name"`
|
|
// FileSize is the total size of the file in bytes (-1 if unknown)
|
|
FileSize int64 `json:"file_size"`
|
|
// ChunkSize is the size of each chunk in bytes
|
|
ChunkSize int64 `json:"chunk_size"`
|
|
// ChunksExpected is the expected number of chunks (-1 if unknown)
|
|
ChunksExpected int64 `json:"chunks_expected"`
|
|
// ChunksReceived is the number of chunks received so far
|
|
ChunksReceived int64 `json:"chunks_received"`
|
|
// BytesReceived is the total number of bytes received so far
|
|
BytesReceived int64 `json:"bytes_received"`
|
|
// ReceivedChunks is the list of chunk numbers that have been received
|
|
ReceivedChunks []int64 `json:"received_chunks"`
|
|
// Status is the current status of the upload session (active, complete, expired, failed)
|
|
Status string `json:"status"`
|
|
// ExpiresAt is the Unix timestamp when this session expires
|
|
ExpiresAt int64 `json:"expires_at"`
|
|
}
|