package utils import ( "context" "fmt" "io" "net/url" "github.com/fiskerinc/cloud-services/pkg/remotefileupload" "github.com/Azure/azure-storage-blob-go/azblob" "github.com/pkg/errors" ) func ReadAzureBlob(azureContainer string, vin string, year, month, day int, offset, count int64, readDirection Direction) ([]byte, int64, error) { creds, err := AzureStorageCredential() if err != nil { return nil, -1, err } link, err := remotefileupload.AzureFilePathLink(AzureAccount, azureContainer, vin, fmt.Sprintf("%04d", year), fmt.Sprintf("%02d", month), fmt.Sprintf("%02d", day), ReadFileName) if err != nil { return nil, 0, err } u, err := url.Parse(link) if err != nil { return nil, -1, errors.WithStack(err) } url := azblob.NewBlobURL(*u, azblob.NewPipeline(creds, azblob.PipelineOptions{Retry: azblob.RetryOptions{MaxTries: 100}})) prop, err := url.GetProperties(context.Background(), azblob.BlobAccessConditions{}, azblob.ClientProvidedKeyOptions{}) if err != nil { return nil, -1, err } if offset >= prop.ContentLength() { return nil, -1, errors.New("offset out of range") } //count from the end of the blob readOffset := prop.ContentLength() - offset begin := readOffset if readDirection == Up { begin -= count } //just read the rest if begin <= 0 { begin = 0 count = readOffset } if count == 0 { count = azblob.CountToEnd } reader, err := url.Download(context.Background(), begin, count, azblob.BlobAccessConditions{}, false, azblob.ClientProvidedKeyOptions{}) if err != nil { return nil, -1, err } buf := make([]byte, reader.ContentLength()) _, err = io.ReadAtLeast(reader.Body(azblob.RetryReaderOptions{}), buf, len(buf)) return buf, prop.ContentLength(), err }