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