mirror of
https://github.com/jkaninda/go-storage.git
synced 2026-03-09 11:09:02 +01:00
156 lines
4.0 KiB
Go
156 lines
4.0 KiB
Go
package go_storage
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
|
|
)
|
|
|
|
// AzureStorage implements Storage interface for Azure Blob Storage.
|
|
type AzureStorage struct {
|
|
client *azblob.Client
|
|
container string
|
|
}
|
|
|
|
// NewAzureStorage creates a new Azure Blob Storage instance.
|
|
func NewAzureStorage(config Config) (*AzureStorage, error) {
|
|
if err := validateConfig(config, map[string]string{
|
|
"container": config.AzureContainer,
|
|
}); err != nil {
|
|
return nil, fmt.Errorf("azure: %w", err)
|
|
}
|
|
|
|
// Try to get credentials from environment if not provided
|
|
account := config.AzureAccount
|
|
if account == "" {
|
|
account = os.Getenv("AZURE_STORAGE_ACCOUNT")
|
|
}
|
|
|
|
key := config.AzureKey
|
|
if key == "" {
|
|
key = os.Getenv("AZURE_STORAGE_KEY")
|
|
}
|
|
|
|
endpoint := config.AzureEndpoint
|
|
if endpoint == "" {
|
|
endpoint = "blob.core.windows.net"
|
|
}
|
|
|
|
var client *azblob.Client
|
|
var err error
|
|
|
|
if account == "" {
|
|
// Anonymous access
|
|
client, err = azblob.NewClientWithNoCredential(endpoint, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("azure: failed to create anonymous client: %w", err)
|
|
}
|
|
} else {
|
|
// Authenticated access
|
|
credential, err := azblob.NewSharedKeyCredential(account, key)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("azure: failed to create credentials: %w", err)
|
|
}
|
|
|
|
url := fmt.Sprintf("https://%s.%s", account, endpoint)
|
|
|
|
client, err = azblob.NewClientWithSharedKeyCredential(url, credential, nil)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("azure: failed to create client: %w", err)
|
|
}
|
|
}
|
|
|
|
return &AzureStorage{
|
|
client: client,
|
|
container: config.AzureContainer,
|
|
}, nil
|
|
}
|
|
|
|
// Upload uploads a file to Azure Blob Storage.
|
|
func (a *AzureStorage) Upload(ctx context.Context, localPath string, remotePath string) error {
|
|
file, err := os.Open(localPath)
|
|
if err != nil {
|
|
return fmt.Errorf("azure: failed to open local file: %w", err)
|
|
}
|
|
defer func(file *os.File) {
|
|
err = file.Close()
|
|
if err != nil {
|
|
fmt.Printf("azure: failed to close file: %v\n", err)
|
|
}
|
|
}(file)
|
|
|
|
_, err = a.client.UploadFile(ctx, a.container, normalizePathSeparators(remotePath), file, nil)
|
|
if err != nil {
|
|
return fmt.Errorf("azure: failed to upload to container %s: %w", a.container, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Download downloads a file from Azure Blob Storage.
|
|
func (a *AzureStorage) Download(ctx context.Context, remotePath string, localPath string) error {
|
|
file, err := os.Create(localPath)
|
|
if err != nil {
|
|
return fmt.Errorf("azure: failed to create local file: %w", err)
|
|
}
|
|
defer func(file *os.File) {
|
|
err = file.Close()
|
|
if err != nil {
|
|
fmt.Printf("azure: failed to close file: %v\n", err)
|
|
}
|
|
}(file)
|
|
|
|
_, err = a.client.DownloadFile(ctx, a.container, normalizePathSeparators(remotePath), file, nil)
|
|
if err != nil {
|
|
return fmt.Errorf("azure: failed to download from container %s: %w", a.container, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// List lists blobs in Azure Blob Storage with the given prefix.
|
|
func (a *AzureStorage) List(ctx context.Context, prefix string) ([]Item, error) {
|
|
normalizedPrefix := normalizePathSeparators(prefix)
|
|
|
|
pager := a.client.NewListBlobsFlatPager(a.container, &azblob.ListBlobsFlatOptions{
|
|
Prefix: &normalizedPrefix,
|
|
})
|
|
|
|
items := make([]Item, 0)
|
|
|
|
for pager.More() {
|
|
resp, err := pager.NextPage(ctx)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("azure: failed to list blobs in container %s: %w", a.container, err)
|
|
}
|
|
|
|
for _, blob := range resp.Segment.BlobItems {
|
|
items = append(items, Item{
|
|
Key: *blob.Name,
|
|
ModifiedTime: *blob.Properties.LastModified,
|
|
Size: *blob.Properties.ContentLength,
|
|
IsDirectory: false,
|
|
})
|
|
}
|
|
}
|
|
|
|
return items, nil
|
|
}
|
|
|
|
// Remove deletes a blob from Azure Blob Storage.
|
|
func (a *AzureStorage) Remove(ctx context.Context, remotePath string) error {
|
|
_, err := a.client.DeleteBlob(ctx, a.container, normalizePathSeparators(remotePath), nil)
|
|
if err != nil {
|
|
return fmt.Errorf("azure: failed to remove blob from container %s: %w", a.container, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Close releases resources.
|
|
func (a *AzureStorage) Close() error {
|
|
return nil
|
|
}
|