ultisuite-backend/internal/nextcloud/upload_streaming.go
R3D347HR4Y 1ffd0817d8
Some checks are pending
CI / Go tests (push) Waiting to run
CI / Integration tests (push) Waiting to run
CI / DB migrations (push) Waiting to run
feat(migration): enhance migration API with roster and audit export features
- Added endpoints for listing and importing migration rosters.
- Introduced audit export functionality for migration jobs in CSV and NDJSON formats.
- Implemented tenant mismatch validation for Microsoft migration claims.
- Enhanced error handling for email claiming and migration processes.
- Added integration tests for roster import and claim workflows.
2026-06-13 13:11:30 +02:00

66 lines
1.5 KiB
Go

package nextcloud
import (
"bytes"
"context"
"crypto/rand"
"encoding/hex"
"fmt"
"io"
)
const defaultUploadChunkSize = 10 * 1024 * 1024
// UploadStreaming uploads large files via Nextcloud chunked DAV assembly.
func (c *Client) UploadStreaming(ctx context.Context, userID, targetPath string, content io.Reader, contentType string, totalSize int64) error {
uploadID, err := newChunkUploadID()
if err != nil {
return err
}
buf := make([]byte, defaultUploadChunkSize)
var uploaded int64
chunkIndex := 0
for {
n, readErr := io.ReadFull(content, buf)
if n == 0 && readErr == io.EOF {
break
}
if n > 0 {
chunkIndex++
if err := c.UploadChunk(ctx, userID, uploadID, chunkIndexName(chunkIndex), bytes.NewReader(buf[:n]), contentType); err != nil {
_ = c.AbortChunkUpload(ctx, userID, uploadID)
return err
}
uploaded += int64(n)
}
if readErr == io.EOF || readErr == io.ErrUnexpectedEOF {
break
}
if readErr != nil {
_ = c.AbortChunkUpload(ctx, userID, uploadID)
return readErr
}
}
finalSize := uploaded
if totalSize > 0 {
finalSize = totalSize
}
if err := c.AssembleChunks(ctx, userID, uploadID, targetPath, finalSize); err != nil {
_ = c.AbortChunkUpload(ctx, userID, uploadID)
return err
}
return nil
}
func newChunkUploadID() (string, error) {
b := make([]byte, 16)
if _, err := rand.Read(b); err != nil {
return "", fmt.Errorf("chunk upload id: %w", err)
}
return hex.EncodeToString(b), nil
}
func chunkIndexName(index int) string {
return fmt.Sprintf("%d", index)
}