diff --git a/interfaces/storage.go b/interfaces/storage.go index dff0cfd..a5afc7b 100644 --- a/interfaces/storage.go +++ b/interfaces/storage.go @@ -18,7 +18,7 @@ type StorageService interface { FileExists(hash []byte) (bool, models.Upload) GetHashSmall(file io.ReadSeeker) ([]byte, error) GetHash(file io.Reader) ([]byte, int64, error) - GetFile(hash []byte) (io.ReadCloser, uint64, error) + GetFile(hash []byte, start int64) (io.ReadCloser, int64, error) CreateUpload(hash []byte, uploaderID uint, uploaderIP string, size uint64, protocol string) (*models.Upload, error) TusUploadExists(hash []byte) (bool, models.TusUpload) CreateTusUpload(hash []byte, uploadID string, uploaderID uint, uploaderIP string, protocol string) (*models.TusUpload, error) diff --git a/storage/storage.go b/storage/storage.go index c0da20f..5a3289f 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -5,6 +5,7 @@ import ( "context" "encoding/hex" "errors" + "fmt" "git.lumeweb.com/LumeWeb/libs5-go/encoding" "git.lumeweb.com/LumeWeb/libs5-go/types" "git.lumeweb.com/LumeWeb/portal/api/middleware" @@ -23,6 +24,7 @@ import ( "go.uber.org/zap" "io" "lukechampine.com/blake3" + "net/http" "strings" "time" ) @@ -598,7 +600,7 @@ func splitS3Ids(id string) (objectId, multipartId string) { return } -func (s *StorageServiceImpl) GetFile(hash []byte) (io.ReadCloser, uint64, error) { +func (s *StorageServiceImpl) GetFile(hash []byte, start int64) (io.ReadCloser, int64, error) { if exists, tusUpload := s.TusUploadExists(hash); exists { if tusUpload.Completed { upload, err := s.tusStore.GetUpload(context.Background(), tusUpload.UploadID) @@ -607,10 +609,9 @@ func (s *StorageServiceImpl) GetFile(hash []byte) (io.ReadCloser, uint64, error) } info, _ := upload.GetInfo(context.Background()) - reader, err := upload.GetReader(context.Background()) - return reader, uint64(info.Size), err + return reader, info.Size, err } } @@ -625,16 +626,26 @@ func (s *StorageServiceImpl) GetFile(hash []byte) (io.ReadCloser, uint64, error) return nil, 0, err } - resp, err := s.httpApi.R(). + request := s.httpApi.R(). SetPathParam("path", hashStr). SetQueryParam("bucket", upload.Protocol). - DisableAutoReadResponse(). - Get("/api/worker/objects/{path}") + DisableAutoReadResponse() + + if start > 0 { + rangeHeader := fmt.Sprintf("bytes=%d-", start) + request.SetHeader("Range", rangeHeader) + } + + resp, err := request.Get("/api/worker/objects/{path}") if err != nil { return nil, 0, err } + if start > 0 && resp.StatusCode != http.StatusPartialContent { + return nil, 0, fmt.Errorf("unexpected status code: %d", resp.StatusCode) + } + if resp.IsError() { if resp.Error() != nil { return nil, 0, resp.Error().(error) @@ -644,5 +655,5 @@ func (s *StorageServiceImpl) GetFile(hash []byte) (io.ReadCloser, uint64, error) } - return resp.Body, upload.Size, nil + return resp.Body, int64(upload.Size), nil }