@@ -2,6 +2,7 @@ package download
22
33import (
44 "fmt"
5+ "io"
56 "net/http"
67 "net/url"
78 "os"
@@ -73,44 +74,53 @@ func NewBlobDownload(accountName, accountKey string, blob blobutil.AzureBlobRef)
7374// GetSASBlob download a blob with specified uri and sas authorization and saves it to the target directory
7475// Returns the filePath where the blob was downloaded
7576func GetSASBlob (blobURI , blobSas , targetDir string ) (string , error ) {
76- bloburl , err := url .Parse (blobURI + blobSas )
77+ blobFullURL := blobURI + blobSas
78+
7779 loggableBlobUri := GetUriForLogging (blobURI )
78- if err != nil {
79- return "" , errors .Wrapf (err , "unable to parse URL: %q" , loggableBlobUri )
80- }
8180
82- containerRef , err := storage . GetContainerReferenceFromSASURI ( * bloburl )
81+ resp , err := http . Get ( blobFullURL )
8382 if err != nil {
84- return "" , errors .Wrapf (err , "unable to open storage container : %q" , loggableBlobUri )
83+ return "" , errors .Wrapf (err , "Failed to download file : %q" , loggableBlobUri )
8584 }
85+ defer resp .Body .Close () // Ensure the response body is closed after we're done
8686
87- // Extract the blob path after container name
88- fileName , blobPathError := getBlobPathAfterContainerName (blobURI , containerRef .Name )
89- if fileName == "" {
90- return "" , errors .Wrapf (blobPathError , "cannot extract blob path name from URL: %q" , loggableBlobUri )
87+ // Check if the HTTP status code indicates success (e.g., 200 OK)
88+ if resp .StatusCode != http .StatusOK {
89+ return "" , errors .Wrapf (err , "Failed to download file: %q, Http status code: %s" , loggableBlobUri , resp .Status )
9190 }
9291
93- blobref := containerRef .GetBlobReference (fileName )
94- reader , err := blobref .Get (nil )
92+ blobParsedurl , err := url .Parse (blobURI )
9593 if err != nil {
96- return "" , errors .Wrapf (err , "unable to open storage blob: %q" , loggableBlobUri )
94+ return "" , errors .Wrapf (err , "unable to parse URL: %q" , loggableBlobUri )
95+ }
96+ // Extract container name from Path of the url https://<hostName>/<Path> For ex. Path = "containerName/dir1/dir2/file.sh"
97+ trimmedPath := strings .Trim (blobParsedurl .Path , "/" )
98+ splitStrings := strings .Split (trimmedPath , "/" )
99+ containerName := splitStrings [0 ]
100+
101+ // Extract the blob path after container name
102+ fileName , blobPathError := getBlobPathAfterContainerName (blobURI , containerName )
103+ if fileName == "" || blobPathError != nil {
104+ return "" , errors .Wrapf (blobPathError , "Failed to extract blob path name from URL: %q" , loggableBlobUri )
97105 }
98106
107+ // Create the local file
99108 scriptFilePath := filepath .Join (targetDir , fileName )
100109 const mode = 0500 // scripts should have execute permissions
101- file , err := os .OpenFile (scriptFilePath , os .O_WRONLY | os .O_TRUNC | os .O_CREATE , mode )
110+ outFile , err := os .OpenFile (scriptFilePath , os .O_WRONLY | os .O_TRUNC | os .O_CREATE , mode )
102111 if err != nil {
103- return "" , errors .Wrapf (err , "failed to open file '%s' for writing: " , scriptFilePath )
112+ return "" , errors .Wrapf (err , "Failed to open file '%s' for writing: " , scriptFilePath )
104113 }
105- defer file .Close ()
114+ defer outFile .Close () // Ensure the file is closed after we're done
106115
107- var buff = make ([] byte , 1000 )
108- for numBytes , _ := reader . Read ( buff ); numBytes > 0 ; numBytes , _ = reader . Read ( buff ) {
109- writtenBytes , writeErr := file . Write ( buff [: numBytes ])
110- if writtenBytes != numBytes || writeErr != nil {
111- return "" , errors . Wrapf ( writeErr , "failed to write to the file '%s': " , scriptFilePath )
112- }
116+ // Write the body to the file using io.Copy
117+ // io.Copy is efficient for large files as it streams data without
118+ // loading the entire file into memory.
119+ _ , err = io . Copy ( outFile , resp . Body )
120+ if err != nil {
121+ return "" , errors . Wrapf ( err , "Failed to copy data to file '%s'" , scriptFilePath )
113122 }
123+
114124 return scriptFilePath , nil
115125}
116126
0 commit comments