While downloading file from Azure Blob Storage using Golang getting " curl Empty reply from server" , but file is downloaded in background

Issue

I am trying to download a file from Azure Blob Storage using http request. I am able to download the file but on a terminal curl returns “Empty reply from server”. I tried to increase the timeout, but it didn’t fix it. I referred other questions related to this response from curl, but it didn’t help. For small files this code is working flawlessly but for big files say 75 MB it is not working.

    containerURL := azblob.NewContainerURL(*URL, pipeline)

    blobURL := containerURL.NewBlockBlobURL(splitArray[1])

    ctx := context.Background()

    downloadResponse, err := blobURL.Download(ctx, 0, azblob.CountToEnd, azblob.BlobAccessConditions{}, false)

    if err != nil {
    .
    .
    .
    }

    bodyStream := downloadResponse.Body(azblob.RetryReaderOptions{MaxRetryRequests: 20})

    // read the body into a buffer
    downloadedData := bytes.Buffer{}

    _, err = downloadedData.ReadFrom(bodyStream)

    file, err := os.OpenFile(

        "/tmp/"+fileName,

        os.O_RDWR|os.O_TRUNC|os.O_CREATE,

        0777,
    )

    file.Write(downloadedData.Bytes())

    file.Close()

    filePath := "/tmp/" + fileName

    file, err = os.Open(filePath)

    return middleware.ResponderFunc(func(w http.ResponseWriter, r runtime.Producer) {

        fn := filepath.Base(filePath)

        w.Header().Set(CONTENTTYPE, "application/octet-stream")

        w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%q", fn))

        io.Copy(w, file)

        err := defer os.Remove(filePath)

        file.Close()

    })

I am thinking of implementing the above logic using goroutines. Is there even a need of using goroutines?

Any constructive feedback will be helpful.

Solution

After analyzing packets from wireshark got to know it was getting disconnected from my side due to timeout as I am using go-swagger , I increased the timeout , in configure.go . GoSwagger provides in-built function for handling these scenarios like TLS , Timeout. Below is code for reference.

// As soon as server is initialized but not run yet, this function will be called.
// If you need to modify a config, store server instance to stop it individually later, this is the place.
// This function can be called multiple times, depending on the number of serving schemes.
// scheme value will be set accordingly: "http", "https" or "unix"

func configureServer(s *http.Server, scheme, addr string) {
    s.WriteTimeout(time.Minute * 5)
}

Answered By – infiniteLearner

Answer Checked By – Pedro (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.