github.com/Files-com/files-sdk-go/v2@v2.1.2/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/v2"
    12  	"github.com/Files-com/files-sdk-go/v2/file/manager"
    13  	"github.com/Files-com/files-sdk-go/v2/file/status"
    14  	lib "github.com/Files-com/files-sdk-go/v2/lib"
    15  	"github.com/Files-com/files-sdk-go/v2/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 status.Job, opts ...files_sdk.RequestResponseOption) *status.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  			Config:         c.Config,
   161  		},
   162  		opts...,
   163  	)
   164  }
   165  
   166  type UploaderParams struct {
   167  	Ignore  []string
   168  	Include []string
   169  	*status.Job
   170  	Sync       bool
   171  	LocalPath  string
   172  	RemotePath string
   173  	DryRun     bool
   174  	RetryPolicy
   175  	status.EventsReporter
   176  	*manager.Manager
   177  	files_sdk.Config
   178  }
   179  
   180  func expand(path string) (string, error) {
   181  	if len(path) == 0 || path[0] != '~' {
   182  		return path, nil
   183  	}
   184  	usr, err := user.Current()
   185  	if err != nil {
   186  		return "", err
   187  	}
   188  	return filepath.Join(usr.HomeDir, path[1:]), nil
   189  }
   190  
   191  func (c *Client) Uploader(params UploaderParams, opts ...files_sdk.RequestResponseOption) *status.Job {
   192  	job := (&status.Job{}).Init()
   193  	SetJobParams(job, direction.UploadType, params, params.Config.Logger(), (&FS{}).Init(c.Config, true))
   194  	job.Config = params.Config
   195  	job.CodeStart = func() {
   196  		params.Job = job
   197  		job.Params = params
   198  		params.RemotePath = lib.Path{Path: params.RemotePath}.PruneStartingSlash().String()
   199  		file := &UploadStatus{file: files_sdk.File{}, remotePath: params.RemotePath, localPath: params.LocalPath, status: status.Queued, job: job}
   200  		expandedPath, err := expand(params.LocalPath)
   201  		if err != nil {
   202  			job.Add(file)
   203  			job.UpdateStatus(status.Errored, file, err)
   204  			return
   205  		}
   206  		absolutePath, err := filepath.Abs(expandedPath)
   207  		if err != nil {
   208  			job.Add(file)
   209  			job.UpdateStatus(status.Errored, file, err)
   210  			return
   211  		}
   212  		if (lib.Path{Path: params.LocalPath}).EndingSlash() {
   213  			params.LocalPath = absolutePath + string(os.PathSeparator)
   214  		} else {
   215  			params.LocalPath = absolutePath
   216  		}
   217  
   218  		uploader(files_sdk.ContextOption(opts), c, params).CodeStart()
   219  	}
   220  
   221  	return job
   222  }