- 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.
66 lines
1.5 KiB
Go
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)
|
|
}
|