github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/backend/fichier/object.go (about)

     1  package fichier
     2  
     3  import (
     4  	"context"
     5  	"io"
     6  	"net/http"
     7  	"time"
     8  
     9  	"github.com/pkg/errors"
    10  	"github.com/rclone/rclone/fs"
    11  	"github.com/rclone/rclone/fs/hash"
    12  	"github.com/rclone/rclone/lib/rest"
    13  )
    14  
    15  // Object is a filesystem like object provided by an Fs
    16  type Object struct {
    17  	fs     *Fs
    18  	remote string
    19  	file   File
    20  }
    21  
    22  // String returns a description of the Object
    23  func (o *Object) String() string {
    24  	return o.file.Filename
    25  }
    26  
    27  // Remote returns the remote path
    28  func (o *Object) Remote() string {
    29  	return o.remote
    30  }
    31  
    32  // ModTime returns the modification date of the file
    33  // It should return a best guess if one isn't available
    34  func (o *Object) ModTime(ctx context.Context) time.Time {
    35  	modTime, err := time.Parse("2006-01-02 15:04:05", o.file.Date)
    36  
    37  	if err != nil {
    38  		return time.Now()
    39  	}
    40  
    41  	return modTime
    42  }
    43  
    44  // Size returns the size of the file
    45  func (o *Object) Size() int64 {
    46  	return o.file.Size
    47  }
    48  
    49  // Fs returns read only access to the Fs that this object is part of
    50  func (o *Object) Fs() fs.Info {
    51  	return o.fs
    52  }
    53  
    54  // Hash returns the selected checksum of the file
    55  // If no checksum is available it returns ""
    56  func (o *Object) Hash(ctx context.Context, t hash.Type) (string, error) {
    57  	if t != hash.Whirlpool {
    58  		return "", hash.ErrUnsupported
    59  	}
    60  
    61  	return o.file.Checksum, nil
    62  }
    63  
    64  // Storable says whether this object can be stored
    65  func (o *Object) Storable() bool {
    66  	return true
    67  }
    68  
    69  // SetModTime sets the metadata on the object to set the modification date
    70  func (o *Object) SetModTime(context.Context, time.Time) error {
    71  	return fs.ErrorCantSetModTime
    72  	//return errors.New("setting modtime is not supported for 1fichier remotes")
    73  }
    74  
    75  // Open opens the file for read.  Call Close() on the returned io.ReadCloser
    76  func (o *Object) Open(ctx context.Context, options ...fs.OpenOption) (io.ReadCloser, error) {
    77  	fs.FixRangeOption(options, o.file.Size)
    78  	downloadToken, err := o.fs.getDownloadToken(ctx, o.file.URL)
    79  
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  
    84  	var resp *http.Response
    85  	opts := rest.Opts{
    86  		Method:  "GET",
    87  		RootURL: downloadToken.URL,
    88  		Options: options,
    89  	}
    90  
    91  	err = o.fs.pacer.Call(func() (bool, error) {
    92  		resp, err = o.fs.rest.Call(ctx, &opts)
    93  		return shouldRetry(resp, err)
    94  	})
    95  
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  	return resp.Body, err
   100  }
   101  
   102  // Update in to the object with the modTime given of the given size
   103  //
   104  // When called from outside an Fs by rclone, src.Size() will always be >= 0.
   105  // But for unknown-sized objects (indicated by src.Size() == -1), Upload should either
   106  // return an error or update the object properly (rather than e.g. calling panic).
   107  func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, options ...fs.OpenOption) error {
   108  	if src.Size() < 0 {
   109  		return errors.New("refusing to update with unknown size")
   110  	}
   111  
   112  	// upload with new size but old name
   113  	info, err := o.fs.putUnchecked(ctx, in, o.Remote(), src.Size(), options...)
   114  	if err != nil {
   115  		return err
   116  	}
   117  
   118  	// Delete duplicate after successful upload
   119  	err = o.Remove(ctx)
   120  	if err != nil {
   121  		return errors.Wrap(err, "failed to remove old version")
   122  	}
   123  
   124  	// Replace guts of old object with new one
   125  	*o = *info.(*Object)
   126  
   127  	return nil
   128  }
   129  
   130  // Remove removes this object
   131  func (o *Object) Remove(ctx context.Context) error {
   132  	// fs.Debugf(f, "Removing file `%s` with url `%s`", o.file.Filename, o.file.URL)
   133  
   134  	_, err := o.fs.deleteFile(ctx, o.file.URL)
   135  
   136  	if err != nil {
   137  		return err
   138  	}
   139  
   140  	return nil
   141  }
   142  
   143  // MimeType of an Object if known, "" otherwise
   144  func (o *Object) MimeType(ctx context.Context) string {
   145  	return o.file.ContentType
   146  }
   147  
   148  // ID returns the ID of the Object if known, or "" if not
   149  func (o *Object) ID() string {
   150  	return o.file.URL
   151  }
   152  
   153  // Check the interfaces are satisfied
   154  var (
   155  	_ fs.Object    = (*Object)(nil)
   156  	_ fs.MimeTyper = (*Object)(nil)
   157  	_ fs.IDer      = (*Object)(nil)
   158  )