func (a *DefaultClient) List(l vfs.Location) ([]string, error) {
	URL, err := url.Parse(l.(*Location).ContainerURL())
	if err != nil {
		return []string{}, err
	}
	containerURL := azblob.NewContainerURL(*URL, a.pipeline)
	ctx := context.Background()
	var list []string
	for marker := (azblob.Marker{}); marker.NotDone(); {
		listBlob, err := containerURL.ListBlobsHierarchySegment(ctx, marker, "/",
			azblob.ListBlobsSegmentOptions{Prefix: utils.RemoveLeadingSlash(l.Path())})
		if err != nil {
			return []string{}, err
		}
		marker = listBlob.NextMarker
		for i := range listBlob.Segment.BlobItems {
			list = append(list, listBlob.Segment.BlobItems[i].Name)
		}
	}
	return list, nil
}
List will return a listing of the contents of the given location.  Each item in the list will contain the full key
as specified by the azure blob (incliding the virtual 'path').
package azure
import (
	"context"
	"fmt"
	"io"
	"net/url"
	"strings"
	"time"
	"github.com/Azure/azure-pipeline-go/pipeline"
	"github.com/Azure/azure-storage-blob-go/azblob"
	"github.com/c2fo/vfs/v6"
	"github.com/c2fo/vfs/v6/utils"
)
type Client interface {
	Properties(locationURI, filePath string) (*BlobProperties, error)
	SetMetadata(file vfs.File, metadata map[string]string) error
	Upload(file vfs.File, content io.ReadSeeker) error
	Download(file vfs.File) (io.ReadCloser, error)
	Copy(srcFile vfs.File, tgtFile vfs.File) error
	List(l vfs.Location) ([]string, error)
	Delete(file vfs.File) error
}
type DefaultClient struct {
	pipeline pipeline.Pipeline
}
func NewClient(options *Options) (*DefaultClient, error) {
	credential, err := options.Credential()
	if err != nil {
		return nil, err
	}
	pl := azblob.NewPipeline(credential, azblob.PipelineOptions{})
	return &DefaultClient{pl}, nil
}
func (a *DefaultClient) Properties(containerURI, filePath string) (*BlobProperties, error) {
	URL, err := url.Parse(containerURI)
	if err != nil {
		return nil, err
	}
	containerURL := azblob.NewContainerURL(*URL, a.pipeline)
	if filePath == "" {
		_, err := containerURL.GetProperties(context.Background(), azblob.LeaseAccessConditions{})
		if err != nil {
			return nil, err
		}
		return nil, nil
	}
	blobURL := containerURL.NewBlockBlobURL(utils.RemoveLeadingSlash(filePath))
	resp, err := blobURL.GetProperties(context.Background(), azblob.BlobAccessConditions{}, azblob.ClientProvidedKeyOptions{})
	if err != nil {
		return nil, err
	}
	return NewBlobProperties(resp), nil
}
func (a *DefaultClient) Upload(file vfs.File, content io.ReadSeeker) error {
	URL, err := url.Parse(file.Location().(*Location).ContainerURL())
	if err != nil {
		return err
	}
	containerURL := azblob.NewContainerURL(*URL, a.pipeline)
	blobURL := containerURL.NewBlockBlobURL(utils.RemoveLeadingSlash(file.Path()))
	_, err = blobURL.Upload(context.Background(), content, azblob.BlobHTTPHeaders{}, azblob.Metadata{},
		azblob.BlobAccessConditions{}, azblob.DefaultAccessTier, nil, azblob.ClientProvidedKeyOptions{})
	return err
}
func (a *DefaultClient) SetMetadata(file vfs.File, metadata map[string]string) error {
	URL, err := url.Parse(file.Location().(*Location).ContainerURL())
	if err != nil {
		return err
	}
	containerURL := azblob.NewContainerURL(*URL, a.pipeline)
	blobURL := containerURL.NewBlockBlobURL(utils.RemoveLeadingSlash(file.Path()))
	_, err = blobURL.SetMetadata(context.Background(), metadata, azblob.BlobAccessConditions{}, azblob.ClientProvidedKeyOptions{})
	return err
}
func (a *DefaultClient) Download(file vfs.File) (io.ReadCloser, error) {
	URL, err := url.Parse(file.Location().(*Location).ContainerURL())
	if err != nil {
		return nil, err
	}
	containerURL := azblob.NewContainerURL(*URL, a.pipeline)
	blobURL := containerURL.NewBlockBlobURL(utils.RemoveLeadingSlash(file.Path()))
	get, err := blobURL.Download(context.Background(), 0, 0, azblob.BlobAccessConditions{}, false, azblob.ClientProvidedKeyOptions{})
	if err != nil {
		return nil, err
	}
	return get.Body(azblob.RetryReaderOptions{}), nil
}
func (a *DefaultClient) Copy(srcFile, tgtFile vfs.File) error {
	srcURL, err := url.Parse(strings.Replace(srcFile.URI(), "%", "%25", -1))
	if err != nil {
		return err
	}
	tgtURL, err := url.Parse(tgtFile.Location().(*Location).ContainerURL())
	if err != nil {
		return err
	}
	containerURL := azblob.NewContainerURL(*tgtURL, a.pipeline)
	blobURL := containerURL.NewBlockBlobURL(utils.RemoveLeadingSlash(tgtFile.Path()))
	ctx := context.Background()
	resp, err := blobURL.StartCopyFromURL(ctx, *srcURL, azblob.Metadata{}, azblob.ModifiedAccessConditions{},
		azblob.BlobAccessConditions{}, azblob.DefaultAccessTier, nil)
	if err != nil {
		return err
	}
	for resp.CopyStatus() == azblob.CopyStatusPending {
		time.Sleep(2 * time.Second)
	}
	if resp.CopyStatus() == azblob.CopyStatusSuccess {
		return nil
	}
	return fmt.Errorf("copy failed ERROR[%s]", resp.ErrorCode())
}