github.com/Files-com/files-sdk-go/v3@v3.1.81/file/upload.go (about)

     1  package file
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"os"
     7  	"os/user"
     8  	"path/filepath"
     9  	"time"
    10  
    11  	files_sdk "github.com/Files-com/files-sdk-go/v3"
    12  	"github.com/Files-com/files-sdk-go/v3/file/manager"
    13  	"github.com/Files-com/files-sdk-go/v3/file/status"
    14  	lib "github.com/Files-com/files-sdk-go/v3/lib"
    15  	"github.com/Files-com/files-sdk-go/v3/lib/direction"
    16  )
    17  
    18  type UploadOption func(uploadIO) (uploadIO, error)
    19  
    20  func UploadWithContext(ctx context.Context) UploadOption {
    21  	return func(params uploadIO) (uploadIO, error) {
    22  		params.passedInContext = ctx
    23  		return params, nil
    24  	}
    25  }
    26  
    27  func UploadWithReader(reader io.Reader) UploadOption {
    28  	return func(params uploadIO) (uploadIO, error) {
    29  		if lenReader, ok := reader.(Len); ok && params.Size == nil {
    30  			params.Size = lib.Int64(int64(lenReader.Len()))
    31  		}
    32  		params.reader = reader
    33  		return params, nil
    34  	}
    35  }
    36  
    37  func UploadWithReaderAt(readerAt io.ReaderAt) UploadOption {
    38  	return func(params uploadIO) (uploadIO, error) {
    39  		if lenReader, ok := readerAt.(Len); ok && params.Size == nil {
    40  			params.Size = lib.Int64(int64(lenReader.Len()))
    41  		}
    42  		params.readerAt = readerAt
    43  		return params, nil
    44  	}
    45  }
    46  
    47  func UploadWithFile(sourcePath string) UploadOption {
    48  	return func(params uploadIO) (uploadIO, error) {
    49  		file, err := os.Open(sourcePath)
    50  		if err != nil {
    51  			return params, err
    52  		}
    53  		info, err := file.Stat()
    54  		if err != nil {
    55  			return params, err
    56  		}
    57  
    58  		params, err = UploadWithReaderAt(file)(params)
    59  		if err != nil {
    60  			return params, err
    61  		}
    62  		return UploadWithSize(info.Size())(params)
    63  	}
    64  }
    65  
    66  func UploadWithDestinationPath(destinationPath string) UploadOption {
    67  	return func(params uploadIO) (uploadIO, error) {
    68  		params.Path = destinationPath
    69  		return params, nil
    70  	}
    71  }
    72  
    73  func UploadWithProvidedMtime(providedMtime time.Time) UploadOption {
    74  	return func(params uploadIO) (uploadIO, error) {
    75  		params.ProvidedMtime = providedMtime
    76  		return params, nil
    77  	}
    78  }
    79  
    80  func UploadWithManager(manager lib.ConcurrencyManagerWithSubWorker) UploadOption {
    81  	return func(params uploadIO) (uploadIO, error) {
    82  		params.Manager = manager
    83  		return params, nil
    84  	}
    85  }
    86  
    87  func UploadWithSize(size int64) UploadOption {
    88  	return func(params uploadIO) (uploadIO, error) {
    89  		params.Size = &size
    90  		return params, nil
    91  	}
    92  }
    93  
    94  func UploadWithProgress(progress Progress) UploadOption {
    95  	return func(params uploadIO) (uploadIO, error) {
    96  		params.Progress = progress
    97  		return params, nil
    98  	}
    99  }
   100  
   101  // UploadRewindAllProgressOnFailure on upload failure rewind all successfully parts
   102  func UploadRewindAllProgressOnFailure() UploadOption {
   103  	return func(params uploadIO) (uploadIO, error) {
   104  		params.RewindAllProgressOnFailure = true
   105  		return params, nil
   106  	}
   107  }
   108  
   109  func UploadWithResume(resume UploadResumable) UploadOption {
   110  	return func(params uploadIO) (uploadIO, error) {
   111  		if params.Path == "" {
   112  			params.Path = resume.FileUploadPart.Path
   113  		}
   114  		params.Parts = resume.Parts
   115  		params.FileUploadPart = resume.FileUploadPart
   116  		return params, nil
   117  	}
   118  }
   119  
   120  func (c *Client) Upload(opts ...UploadOption) error {
   121  	_, err := c.UploadWithResume(opts...)
   122  
   123  	return err
   124  }
   125  
   126  func (c *Client) UploadWithResume(opts ...UploadOption) (UploadResumable, error) {
   127  	uploadIo := uploadIO{
   128  		Client:          c,
   129  		Manager:         manager.Default().FilePartsManager,
   130  		passedInContext: context.Background(),
   131  		ByteOffset:      ByteOffset{PartSizes: lib.PartSizes},
   132  	}
   133  
   134  	for _, opt := range opts {
   135  		var err error
   136  		uploadIo, err = opt(uploadIo)
   137  		if err != nil {
   138  			return UploadResumable{}, err
   139  		}
   140  	}
   141  	return (&uploadIo).Run(uploadIo.passedInContext)
   142  }
   143  
   144  // UploadFile Deprecated use c.Upload(UploadWithFile(sourcePath), UploadWithDestinationPath(destinationPath))
   145  func (c *Client) UploadFile(sourcePath string, destinationPath string, opts ...UploadOption) error {
   146  	return c.Upload(append(opts, UploadWithFile(sourcePath), UploadWithDestinationPath(destinationPath))...)
   147  }
   148  
   149  func (c *Client) UploadRetry(job Job, opts ...files_sdk.RequestResponseOption) *Job {
   150  	newJob := job.ClearStatuses()
   151  	return c.Uploader(
   152  		UploaderParams{
   153  			Sync:           newJob.Sync,
   154  			LocalPath:      newJob.LocalPath,
   155  			RemotePath:     newJob.RemotePath,
   156  			EventsReporter: newJob.EventsReporter,
   157  			Manager:        newJob.Manager,
   158  			RetryPolicy:    newJob.RetryPolicy.(RetryPolicy),
   159  			Ignore:         newJob.Params.(UploaderParams).Ignore,
   160  		},
   161  		opts...,
   162  	)
   163  }
   164  
   165  type UploaderParams struct {
   166  	// Ignore gitignore formatted pattern
   167  	Ignore []string
   168  	// Include gitignore formatted pattern
   169  	Include []string
   170  	// Sync compare destination and only upload if different or non-existent.
   171  	Sync bool
   172  	// LocalPaths files or directories to upload.
   173  	LocalPaths []string
   174  	// LocalPath a file or directory to recursively upload.
   175  	LocalPath string
   176  	// RemotePath destination path for files.com, formatted `/` path separator.
   177  	RemotePath string
   178  	// DryRun see what files would be uploaded.
   179  	DryRun bool
   180  	// RetryPolicy config for retrying errored uploads.
   181  	RetryPolicy
   182  	// EventsReporter log file events
   183  	EventsReporter
   184  	// Manager limit concurrency
   185  	*manager.Manager
   186  	*Job
   187  	config        files_sdk.Config
   188  	PreserveTimes bool
   189  }
   190  
   191  func expand(path string) (string, error) {
   192  	if len(path) == 0 || path[0] != '~' {
   193  		return path, nil
   194  	}
   195  	usr, err := user.Current()
   196  	if err != nil {
   197  		return "", err
   198  	}
   199  	return filepath.Join(usr.HomeDir, path[1:]), nil
   200  }
   201  
   202  func (c *Client) Uploader(params UploaderParams, opts ...files_sdk.RequestResponseOption) *Job {
   203  	job := (&Job{}).Init()
   204  	params.config = c.Config
   205  	SetJobParams(job, direction.UploadType, params, c.Logger, (&FS{}).Init(c.Config, true))
   206  	job.Config = params.config
   207  	job.CodeStart = func() {
   208  		params.Job = job
   209  		job.Params = params
   210  		params.RemotePath = lib.Path{Path: params.RemotePath}.PruneStartingSlash().String()
   211  		file := &UploadStatus{file: files_sdk.File{}, remotePath: params.RemotePath, localPath: params.LocalPath, status: status.Queued, job: job}
   212  		expandedPath, err := expand(params.LocalPath)
   213  		if err != nil {
   214  			job.Add(file)
   215  			job.UpdateStatus(status.Errored, file, err)
   216  			return
   217  		}
   218  		absolutePath, err := filepath.Abs(expandedPath)
   219  		if err != nil {
   220  			job.Add(file)
   221  			job.UpdateStatus(status.Errored, file, err)
   222  			return
   223  		}
   224  		if (lib.Path{Path: params.LocalPath}).EndingSlash() {
   225  			params.LocalPath = absolutePath + string(os.PathSeparator)
   226  		} else {
   227  			params.LocalPath = absolutePath
   228  		}
   229  
   230  		uploader(files_sdk.ContextOption(opts), c, params).CodeStart()
   231  	}
   232  
   233  	return job
   234  }