Files
logikonline 7e36d7d55c feat(api): add chunked upload support for large release attachments
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
2026-01-08 08:58:56 -05:00

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"`
}