@@ -3405,6 +3405,75 @@ func (a *Allocation) DownloadDirectory(ctx context.Context, remotePath, localPat
34053405 return nil
34063406}
34073407
3408+ func (a * Allocation ) DownloadObject (ctx context.Context , remotePath string , rangeStart , rangeEnd int64 ) (io.ReadCloser , error ) {
3409+ fm , err := a .GetFileMeta (remotePath )
3410+ if err != nil {
3411+ return nil , err
3412+ }
3413+ if fm .Type != fileref .FILE {
3414+ return nil , errors .New ("invalid_file_type" , "Invalid file type. Expected file type" )
3415+ }
3416+ var (
3417+ startBlock , endBlock int64
3418+ )
3419+ effectiveChunkSize := a .GetChunkReadSize (fm .EncryptedKey != "" )
3420+ fileRangeSize := rangeEnd - rangeStart + 1
3421+ if rangeEnd < rangeStart {
3422+ fileRangeSize = fm .ActualFileSize
3423+ }
3424+ if rangeEnd >= rangeStart {
3425+ startBlock = int64 (rangeStart / effectiveChunkSize )
3426+ if startBlock == 0 {
3427+ startBlock = 1
3428+ }
3429+ if rangeEnd < fileRangeSize {
3430+ endBlock = (fileRangeSize + effectiveChunkSize - 1 ) / effectiveChunkSize
3431+ } else {
3432+ endBlock = int64 (rangeEnd + effectiveChunkSize - 1 ) / effectiveChunkSize
3433+ }
3434+ } else {
3435+ startBlock = 1
3436+ endBlock = 0
3437+ }
3438+
3439+ if rangeEnd == - 1 {
3440+ endBlock = 0
3441+ startBlock = int64 (rangeStart / effectiveChunkSize )
3442+ if startBlock == 0 {
3443+ startBlock = 1
3444+ }
3445+ fileRangeSize = fm .ActualFileSize - rangeStart
3446+ }
3447+ pipeFile := sys .NewPipeFile ()
3448+ wg := & sync.WaitGroup {}
3449+ wg .Add (1 )
3450+ downloadStatusBar := & StatusBar {
3451+ wg : wg ,
3452+ }
3453+ err = a .DownloadByBlocksToFileHandler (pipeFile , remotePath , startBlock , endBlock , numBlockDownloads , false , downloadStatusBar , true )
3454+ if err != nil {
3455+ return nil , err
3456+ }
3457+ go func () {
3458+ wg .Wait ()
3459+ if downloadStatusBar .err != nil {
3460+ pipeFile .CloseWithError (downloadStatusBar .err ) //nolint: errcheck
3461+ } else {
3462+ pipeFile .Close () //nolint: errcheck
3463+ }
3464+ }()
3465+ startOffset := rangeStart - (startBlock - 1 )* effectiveChunkSize
3466+
3467+ if startOffset > 0 {
3468+ _ , err = pipeFile .Seek (startOffset , io .SeekStart )
3469+ if err != nil {
3470+ return nil , err
3471+ }
3472+ }
3473+ lr := sys .NewLimitedReaderCloser (pipeFile .Reader (), fileRangeSize )
3474+ return lr , nil
3475+ }
3476+
34083477// contextCanceled returns whether a context is canceled.
34093478func contextCanceled (ctx context.Context ) bool {
34103479 select {
0 commit comments