godav

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 26, 2025 License: MIT Imports: 11 Imported by: 0

README

CI CodeQL Coverage Status Open Issues Go Report Card GitHub release (latest by date)

godav

🚀 A Go library for WebDAV with full support for Nextcloud chunked uploads and advanced file operations.

Features

  • High-level client for Nextcloud WebDAV
  • Chunked uploads (bypass proxy body-size limits)
  • Recursive directory uploads
  • Progress reporting and verbose logging
  • Skips files that already exist with the same size
  • Performance optimizations:
    • Buffer pooling to reduce memory allocations
    • Automatic retry logic for failed chunks
    • Context support for cancellation
    • Input validation and sanitization
    • Efficient error handling with custom error types
  • Pause/Resume functionality:
    • Pause and resume uploads at any time
    • Automatic checkpoint saving and loading
    • Resume from interruptions or failures
    • Graceful handling of network disconnections

Installation

go get github.com/tlmanz/godav

Usage

package main

import (
	"github.com/tlmanz/godav"
)

func main() {
	client := godav.NewClient("https://nextcloud.example.com/remote.php/dav/", "username", "password")
	config := godav.DefaultConfig()
	config.Verbose = true

	// Upload a single file
	err := client.UploadFile("/path/to/local/file.txt", "remote/path/file.txt", config)
	if err != nil {
		panic(err)
	}

	// Upload a directory recursively
	err = client.UploadDir("/path/to/local/dir", "remote/path/dir", config)
	if err != nil {
		panic(err)
	}
}

Configuration

You can customize upload behavior using the Config struct:

type Config struct {
	ChunkSize       int64                   // Chunk size in bytes (default 10MB)
	SkipExisting    bool                    // Skip files that exist with same size
	Verbose         bool                    // Enable verbose logging
	ProgressFunc    func(info ProgressInfo) // Progress callback with detailed info
	EventFunc       func(info EventInfo)    // Event callback for upload lifecycle
	MaxRetries      int                     // Maximum retry attempts for failed chunks (default 3)
	BufferPool      *BufferPool             // Optional buffer pool for memory reuse
	Controller      *UploadController       // Upload controller for pause/resume (optional)
	CheckpointFunc  func(cp Checkpoint)     // Checkpoint callback for resume functionality
	ResumeFromCheckpoint *Checkpoint        // Resume from this checkpoint (optional)
}
Pause/Resume Functionality

Enable pause and resume for large file uploads:

// Create an upload controller
controller := godav.NewUploadController()
config.Controller = controller

// Setup checkpoint saving
config.CheckpointFunc = func(checkpoint godav.Checkpoint) {
    // Save checkpoint to file, database, etc.
    godav.SaveCheckpoint(checkpoint, "/tmp/upload_checkpoint.json")
}

// Start resumable upload
controller, err := client.UploadFileResumable(localPath, remotePath, config)

// Control upload programmatically
controller.Pause()  // Pause the upload
controller.Resume() // Resume the upload
controller.Cancel() // Cancel the upload

// Resume from a saved checkpoint
checkpoint, err := godav.LoadCheckpoint("/tmp/upload_checkpoint.json")
if err == nil {
    err = client.ResumeUpload(*checkpoint, config)
}
Performance Configuration

For high-performance uploads, configure buffer pooling and retry logic:

config := godav.DefaultConfig()
config.MaxRetries = 5                                    // Retry failed chunks up to 5 times
config.BufferPool = godav.NewBufferPool(config.ChunkSize, 8) // Pool of 8 reusable buffers
Context Support

Use context for cancellation and timeouts:

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Minute)
defer cancel()

err := client.UploadFileWithContext(ctx, localPath, remotePath, config)
if err != nil {
    if err == context.DeadlineExceeded {
        fmt.Println("Upload timed out")
    } else if err == context.Canceled {
        fmt.Println("Upload was cancelled")
    }
}
Progress Tracking

Show upload progress with detailed information:

config.ProgressFunc = func(info godav.ProgressInfo) {
	fmt.Printf("Uploading %s: %.1f%% (chunk %d/%d)\n", 
		info.Filename, info.Percentage, info.ChunkIndex+1, info.TotalChunks)
}
Upload Lifecycle Events

Track different stages of the upload process:

config.EventFunc = func(info godav.EventInfo) {
	switch info.Event {
	case godav.EventUploadStarted:
		fmt.Printf("🚀 Started uploading: %s\n", info.Filename)
	case godav.EventChunkUploaded:
		fmt.Printf("📦 %s\n", info.Message)
	case godav.EventChunksComplete:
		fmt.Printf("✅ All chunks uploaded for: %s\n", info.Filename)
	case godav.EventMoveStarted:
		fmt.Printf("🔄 Moving file to final location: %s\n", info.Filename)
	case godav.EventMoveComplete:
		fmt.Printf("📍 File moved successfully: %s\n", info.Filename)
	case godav.EventUploadComplete:
		fmt.Printf("🎉 Upload completed: %s\n", info.Filename)
	case godav.EventUploadFailed:
		fmt.Printf("❌ Upload failed: %s - %v\n", info.Filename, info.Error)
	case godav.EventUploadSkipped:
		fmt.Printf("⏭️  Skipped: %s - %s\n", info.Filename, info.Message)
	}
}
Available Events
  • EventUploadStarted - Upload process initiated
  • EventChunkUploaded - Individual chunk uploaded
  • EventChunksComplete - All chunks uploaded, before move
  • EventMoveStarted - Starting final move operation
  • EventMoveComplete - Move operation completed
  • EventUploadComplete - Entire upload process finished
  • EventUploadFailed - Upload failed
  • EventUploadSkipped - File skipped (already exists)
  • EventUploadPaused - Upload paused
  • EventUploadResumed - Upload resumed from checkpoint
Error Handling

The library provides detailed error information:

err := client.UploadFile(localPath, remotePath, config)
if err != nil {
    var uploadErr *godav.UploadError
    if errors.As(err, &uploadErr) {
        fmt.Printf("Upload failed: %s (retries: %d)\n", uploadErr.Op, uploadErr.Retries)
    }
}

Performance Tips

  1. Use buffer pooling: Configure BufferPool to reuse memory buffers
  2. Optimize chunk size: Larger chunks = fewer requests, but more memory usage
  3. Set appropriate retries: Balance reliability vs. performance
  4. Use context: Implement timeouts and cancellation for better UX
  5. Enable pause/resume: For large files, use checkpoints to recover from interruptions
  6. Handle signals: Implement graceful shutdown with checkpoint saving

License

This project is licensed under the MIT License.

Documentation

Overview

Package nextcloud provides a high-level client for Nextcloud WebDAV operations, including chunked uploads that bypass proxy body-size limits.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func SaveCheckpoint added in v1.0.0

func SaveCheckpoint(checkpoint Checkpoint, filePath string) error

SaveCheckpoint saves a checkpoint to a file (JSON format)

Types

type BufferPool added in v1.0.0

type BufferPool struct {
	// contains filtered or unexported fields
}

BufferPool manages reusable byte buffers to reduce allocations

func NewBufferPool added in v1.0.0

func NewBufferPool(chunkSize int64, poolSize int) *BufferPool

NewBufferPool creates a new buffer pool with the specified chunk size and pool size

func (*BufferPool) Get added in v1.0.0

func (bp *BufferPool) Get() []byte

Get retrieves a buffer from the pool or creates a new one

func (*BufferPool) Put added in v1.0.0

func (bp *BufferPool) Put(buf []byte)

Put returns a buffer to the pool for reuse

type Checkpoint added in v1.0.0

type Checkpoint struct {
	LocalPath      string    `json:"local_path"`
	RemotePath     string    `json:"remote_path"`
	UploadID       string    `json:"upload_id"`
	FileSize       int64     `json:"file_size"`
	ChunkSize      int64     `json:"chunk_size"`
	BytesUploaded  int64     `json:"bytes_uploaded"`
	ChunksUploaded int       `json:"chunks_uploaded"`
	TotalChunks    int       `json:"total_chunks"`
	Timestamp      time.Time `json:"timestamp"`
	Config         *Config   `json:"config,omitempty"`
}

Checkpoint represents a resumable upload checkpoint

func LoadCheckpoint added in v1.0.0

func LoadCheckpoint(filePath string) (*Checkpoint, error)

LoadCheckpoint loads a checkpoint from a file

type Client

type Client struct {
	*gowebdav.Client
	// contains filtered or unexported fields
}

Client wraps a gowebdav.Client with Nextcloud-specific operations.

func NewClient

func NewClient(baseURL, username, password string) *Client

NewClient creates a new Nextcloud WebDAV client.

func (*Client) ResumeUpload added in v1.0.0

func (c *Client) ResumeUpload(checkpoint Checkpoint, config *Config) error

ResumeUpload resumes an upload from a checkpoint

func (*Client) SetVerbose

func (c *Client) SetVerbose(verbose bool)

SetVerbose enables or disables verbose logging.

func (*Client) UploadDir

func (c *Client) UploadDir(localDir, dstDir string, config *Config) error

UploadDir uploads a directory recursively using chunked uploads.

func (*Client) UploadFile

func (c *Client) UploadFile(localPath, dstPath string, config *Config) error

UploadFile uploads a single file using Nextcloud's chunked upload protocol. The dstPath is relative to the user's files directory.

func (*Client) UploadFileResumable added in v1.0.0

func (c *Client) UploadFileResumable(localPath, dstPath string, config *Config) (*UploadController, error)

UploadFileResumable uploads a file with built-in pause/resume support

func (*Client) UploadFileWithContext added in v1.0.0

func (c *Client) UploadFileWithContext(ctx context.Context, localPath, dstPath string, config *Config) error

UploadFileWithContext uploads a single file with context support for cancellation.

type Config

type Config struct {
	ChunkSize            int64                   // Chunk size in bytes (default 10MB)
	SkipExisting         bool                    // Skip files that exist with same size
	Verbose              bool                    // Enable verbose logging
	ProgressFunc         func(info ProgressInfo) // Progress callback with detailed info
	EventFunc            func(info EventInfo)    // Event callback for upload lifecycle
	MaxRetries           int                     // Maximum retry attempts for failed chunks (default 3)
	BufferPool           *BufferPool             // Optional buffer pool for memory reuse
	Controller           *UploadController       // Upload controller for pause/resume (optional)
	CheckpointFunc       func(cp Checkpoint)     // Checkpoint callback for resume functionality
	ResumeFromCheckpoint *Checkpoint             // Resume from this checkpoint (optional)
}

Config holds options for upload operations.

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig returns sensible defaults for upload operations.

type EventInfo added in v1.0.0

type EventInfo struct {
	Event    UploadEvent // Type of event
	Filename string      // Name of the file
	Path     string      // Remote path
	Message  string      // Optional message
	Error    error       // Error if applicable
}

EventInfo contains information about upload events

type ProgressInfo

type ProgressInfo struct {
	Filename    string  // Name of the file being uploaded
	Current     int64   // Bytes uploaded so far
	Total       int64   // Total file size in bytes
	Percentage  float64 // Upload progress as percentage (0.0 to 100.0)
	ChunkIndex  int     // Current chunk number (0-based)
	TotalChunks int     // Total number of chunks
}

ProgressInfo contains detailed progress information for uploads.

type UploadController added in v1.0.0

type UploadController struct {
	// contains filtered or unexported fields
}

UploadController provides pause/resume functionality for uploads

func NewUploadController added in v1.0.0

func NewUploadController() *UploadController

NewUploadController creates a new upload controller

func (*UploadController) Cancel added in v1.0.0

func (uc *UploadController) Cancel()

Cancel cancels the upload

func (*UploadController) Pause added in v1.0.0

func (uc *UploadController) Pause()

Pause pauses the upload

func (*UploadController) Resume added in v1.0.0

func (uc *UploadController) Resume()

Resume resumes the upload

func (*UploadController) State added in v1.0.0

func (uc *UploadController) State() UploadState

State returns the current upload state

type UploadError added in v1.0.0

type UploadError struct {
	Op      string // Operation that failed
	Path    string // File path involved
	Err     error  // Underlying error
	Retries int    // Number of retries attempted
}

UploadError represents errors that occur during upload

func (*UploadError) Error added in v1.0.0

func (e *UploadError) Error() string

func (*UploadError) Unwrap added in v1.0.0

func (e *UploadError) Unwrap() error

type UploadEvent added in v1.0.0

type UploadEvent string

UploadEvent represents different stages of the upload process

const (
	EventUploadStarted  UploadEvent = "upload_started"  // Upload process initiated
	EventChunkUploaded  UploadEvent = "chunk_uploaded"  // Individual chunk uploaded
	EventChunksComplete UploadEvent = "chunks_complete" // All chunks uploaded, before move
	EventMoveStarted    UploadEvent = "move_started"    // Starting final move operation
	EventMoveComplete   UploadEvent = "move_complete"   // Move operation completed
	EventUploadComplete UploadEvent = "upload_complete" // Entire upload process finished
	EventUploadFailed   UploadEvent = "upload_failed"   // Upload failed
	EventUploadSkipped  UploadEvent = "upload_skipped"  // File skipped (already exists)
	EventUploadPaused   UploadEvent = "upload_paused"   // Upload paused
	EventUploadResumed  UploadEvent = "upload_resumed"  // Upload resumed from checkpoint
)

type UploadState added in v1.0.0

type UploadState int

UploadState represents the current state of an upload

const (
	StateRunning UploadState = iota
	StatePaused
	StateCancelled
)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL