github.com/qiniu/go-sdk/v7@v7.27.0/storagev2/uploader/source/source.go (about) 1 package source 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "os" 8 "path/filepath" 9 "sync" 10 "sync/atomic" 11 12 internal_io "github.com/qiniu/go-sdk/v7/internal/io" 13 ) 14 15 type ( 16 // 数据源 17 Source interface { 18 io.Closer 19 20 // 切片 21 Slice(uint64) (Part, error) 22 23 // 数据源 ID 24 SourceID() (string, error) 25 26 // 获取文件,如果数据源不是文件,则返回 nil 27 GetFile() *os.File 28 } 29 30 // 预知大小的数据源 31 SizedSource interface { 32 Source 33 34 // 获取数据源大小 35 TotalSize() (uint64, error) 36 } 37 38 // 可重置的数据源 39 ResetableSource interface { 40 Source 41 42 // 重置数据源 43 Reset() error 44 } 45 46 // 分片 47 Part interface { 48 io.ReadSeeker 49 50 // 分片偏移量 51 Offset() uint64 52 53 // 分片大小 54 Size() uint64 55 56 // 分片编号,从 1 开始 57 PartNumber() uint64 58 } 59 60 seekablePart struct { 61 *io.SectionReader 62 partNumber, offset uint64 63 } 64 65 unseekablePart struct { 66 *bytes.Reader 67 partNumber, offset, size uint64 68 } 69 70 readSeekCloseSource struct { 71 rscra *readSeekCloseReaderAt 72 off uint64 73 sourceID string 74 partNumber uint64 75 m sync.Mutex 76 } 77 78 readSeekCloseReaderAt struct { 79 r internal_io.ReadSeekCloser 80 off int64 81 m sync.Mutex 82 } 83 84 readCloseSource struct { 85 r io.ReadCloser 86 sourceID string 87 offset, partNumber uint64 88 } 89 90 ReadAtSeekCloser interface { 91 io.ReaderAt 92 io.Seeker 93 io.Closer 94 } 95 96 readAtSeekCloseSource struct { 97 r ReadAtSeekCloser 98 off uint64 99 sourceID string 100 partNumber uint64 101 m sync.Mutex 102 } 103 ) 104 105 // 将 io.ReadSeekCloser 封装为数据源 106 func NewReadSeekCloserSource(r internal_io.ReadSeekCloser, sourceID string) Source { 107 return &readSeekCloseSource{rscra: newReadSeekCloseReaderAt(r), sourceID: sourceID} 108 } 109 110 func (rscs *readSeekCloseSource) Slice(n uint64) (Part, error) { 111 rscs.m.Lock() 112 defer rscs.m.Unlock() 113 114 offset := rscs.off 115 if totalSize, err := rscs.TotalSize(); err != nil { 116 return nil, err 117 } else if offset >= totalSize { 118 return nil, nil 119 } else if n > totalSize-offset { 120 n = totalSize - offset 121 } 122 rscs.off += n 123 rscs.partNumber += 1 124 return seekablePart{ 125 io.NewSectionReader(rscs.rscra, int64(offset), int64(n)), 126 rscs.partNumber, 127 uint64(offset), 128 }, nil 129 } 130 131 func (rscs *readSeekCloseSource) TotalSize() (uint64, error) { 132 return rscs.rscra.TotalSize() 133 } 134 135 func (rscs *readSeekCloseSource) SourceID() (string, error) { 136 return rscs.sourceID, nil 137 } 138 139 func (rscs *readSeekCloseSource) Close() error { 140 return rscs.rscra.Close() 141 } 142 143 func (rscs *readSeekCloseSource) Reset() error { 144 rscs.m.Lock() 145 defer rscs.m.Unlock() 146 147 rscs.off = 0 148 rscs.partNumber = 0 149 return nil 150 } 151 152 func (rscs *readSeekCloseSource) GetFile() *os.File { 153 return rscs.rscra.GetFile() 154 } 155 156 func newReadSeekCloseReaderAt(r internal_io.ReadSeekCloser) *readSeekCloseReaderAt { 157 return &readSeekCloseReaderAt{r: r, off: -1} 158 } 159 160 func (rscra *readSeekCloseReaderAt) ReadAt(b []byte, off int64) (n int, err error) { 161 rscra.m.Lock() 162 defer rscra.m.Unlock() 163 164 if rscra.off != off { 165 if rscra.off, err = rscra.r.Seek(off, io.SeekStart); err != nil { 166 return 167 } 168 } 169 n, err = rscra.r.Read(b) 170 rscra.off += int64(n) 171 return 172 } 173 174 func (rscra *readSeekCloseReaderAt) TotalSize() (uint64, error) { 175 rscra.m.Lock() 176 defer rscra.m.Unlock() 177 178 var err error 179 180 if rscra.off < 0 { 181 if rscra.off, err = rscra.r.Seek(0, io.SeekCurrent); err != nil { 182 return 0, err 183 } 184 } 185 len, err := rscra.r.Seek(0, io.SeekEnd) 186 if err != nil { 187 return 0, err 188 } 189 _, err = rscra.r.Seek(rscra.off, io.SeekStart) 190 return uint64(len), err 191 } 192 193 func (rscra *readSeekCloseReaderAt) Close() error { 194 return rscra.r.Close() 195 } 196 197 func (rscra *readSeekCloseReaderAt) GetFile() *os.File { 198 if file, ok := rscra.r.(*os.File); ok { 199 return file 200 } else { 201 return nil 202 } 203 } 204 205 // 将 io.ReadAt + io.Seek + io.Closer 封装为数据源 206 func NewReadAtSeekCloserSource(r ReadAtSeekCloser, sourceID string) Source { 207 return &readAtSeekCloseSource{r: r, sourceID: sourceID} 208 } 209 210 func (racs *readAtSeekCloseSource) Slice(n uint64) (Part, error) { 211 racs.m.Lock() 212 defer racs.m.Unlock() 213 214 offset := racs.off 215 if totalSize, err := racs.TotalSize(); err != nil { 216 return nil, err 217 } else if offset >= totalSize { 218 return nil, nil 219 } else if n > totalSize-offset { 220 n = totalSize - offset 221 } 222 racs.off += n 223 racs.partNumber += 1 224 return seekablePart{ 225 io.NewSectionReader(racs.r, int64(offset), int64(n)), 226 racs.partNumber, 227 uint64(offset), 228 }, nil 229 } 230 231 func (racs *readAtSeekCloseSource) TotalSize() (uint64, error) { 232 curPos, err := racs.r.Seek(0, io.SeekCurrent) 233 if err != nil { 234 return 0, err 235 } 236 totalSize, err := racs.r.Seek(0, io.SeekEnd) 237 if err != nil { 238 return 0, err 239 } 240 if _, err = racs.r.Seek(curPos, io.SeekStart); err != nil { 241 return 0, err 242 } 243 return uint64(totalSize), nil 244 } 245 246 func (racs *readAtSeekCloseSource) SourceID() (string, error) { 247 return racs.sourceID, nil 248 } 249 250 func (racs *readAtSeekCloseSource) Close() error { 251 return racs.r.Close() 252 } 253 254 func (racs *readAtSeekCloseSource) Reset() error { 255 racs.m.Lock() 256 defer racs.m.Unlock() 257 258 racs.off = 0 259 racs.partNumber = 0 260 return nil 261 } 262 263 func (racs *readAtSeekCloseSource) GetFile() *os.File { 264 if file, ok := racs.r.(*os.File); ok { 265 return file 266 } else { 267 return nil 268 } 269 } 270 271 // 将 io.ReadCloser 封装为数据源 272 func NewReadCloserSource(r io.ReadCloser, sourceID string) Source { 273 return &readCloseSource{r: r, sourceID: sourceID} 274 } 275 276 func (rcs *readCloseSource) Slice(n uint64) (Part, error) { 277 buf := make([]byte, n) 278 haveRead, err := io.ReadFull(rcs.r, buf) 279 if err != nil && err != io.ErrUnexpectedEOF && err != io.EOF { 280 return nil, err 281 } else if haveRead == 0 { 282 return nil, nil 283 } 284 return &unseekablePart{ 285 bytes.NewReader(buf[:haveRead]), 286 atomic.AddUint64(&rcs.partNumber, 1), 287 atomic.AddUint64(&rcs.offset, uint64(haveRead)) - uint64(haveRead), 288 uint64(haveRead), 289 }, nil 290 } 291 292 func (rcs *readCloseSource) SourceID() (string, error) { 293 return rcs.sourceID, nil 294 } 295 296 func (rcs *readCloseSource) Close() error { 297 return rcs.r.Close() 298 } 299 300 func (racs *readCloseSource) GetFile() *os.File { 301 if file, ok := racs.r.(*os.File); ok { 302 return file 303 } else { 304 return nil 305 } 306 } 307 308 func (p seekablePart) PartNumber() uint64 { 309 return p.partNumber 310 } 311 312 func (p seekablePart) Offset() uint64 { 313 return p.offset 314 } 315 316 func (p seekablePart) Size() uint64 { 317 return uint64(p.SectionReader.Size()) 318 } 319 320 func (p unseekablePart) PartNumber() uint64 { 321 return p.partNumber 322 } 323 324 func (p unseekablePart) Offset() uint64 { 325 return p.offset 326 } 327 328 func (p unseekablePart) Size() uint64 { 329 return p.size 330 } 331 332 // 将文件封装为数据源 333 func NewFileSource(filePath string) (Source, error) { 334 file, err := os.Open(filePath) 335 if err != nil { 336 return nil, err 337 } 338 if !canSeekReally(file) { 339 return NewReadCloserSource(file, ""), nil 340 } else if absFilePath, err := filepath.Abs(filePath); err != nil { 341 return nil, err 342 } else if fileInfo, err := file.Stat(); err != nil { 343 return nil, err 344 } else { 345 sourceID := fmt.Sprintf("%d:%d:%s", fileInfo.Size(), fileInfo.ModTime().UnixNano(), absFilePath) 346 return NewReadAtSeekCloserSource(file, sourceID), nil 347 } 348 } 349 350 func canSeekReally(seeker io.Seeker) bool { 351 _, err := seeker.Seek(0, io.SeekCurrent) 352 return err == nil 353 }