func DownloadFile()

in internal/platform/utils/utils.go [131:222]


func DownloadFile(filepath string, url string, auth string, spinner *pterm.SpinnerPrinter) error {
	headReq, err := http.NewRequest("HEAD", url, nil)
	if err != nil {
		return fmt.Errorf("error creating HEAD request: %w", err)
	}
	if auth != "" {
		headReq.Header.Add("Authorization", fmt.Sprintf("Bearer %s", auth))
	}
	response, err := http.DefaultClient.Do(headReq)
	if err != nil {
		return fmt.Errorf("error making HEAD request: %w", err)
	}
	if response.StatusCode != http.StatusOK {
		return fmt.Errorf("response from %s (HEAD): %s", url, response.Status)
	}

	sizeStr := response.Header.Get("Content-Length")
	if sizeStr == "" {
		sizeStr = "-1"
	}
	size, err := strconv.Atoi(sizeStr)
	if err != nil {
		return fmt.Errorf("error converting Content-Length to integer: %w", err)
	}

	getReq, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return fmt.Errorf("error creating GET request: %w", err)
	}
	if auth != "" {
		getReq.Header.Add("Authorization", fmt.Sprintf("Bearer %s", auth))
	}
	resp, err := http.DefaultClient.Do(getReq)
	if err != nil {
		return fmt.Errorf("error making GET request: %w", err)
	}

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("response from %s (GET): %s", url, resp.Status)
	}
	defer func(Body io.ReadCloser) {
		if err := Body.Close(); err != nil {
			fmt.Printf("Error while closing HTTP stream: %v\n", err)
		}
	}(resp.Body)

	out, err := os.Create(filepath)
	if err != nil {
		return fmt.Errorf("error creating file: %w", err)
	}
	defer func(out *os.File) {
		if err := out.Close(); err != nil {
			fmt.Printf("Error while closing output file: %v\n", err)
		}
	}(out)

	buffer := make([]byte, 1024)
	total := 0
	lastTotal := 0
	text := ""
	if spinner != nil {
		text = spinner.Text
	}
	for {
		length, err := resp.Body.Read(buffer)
		if err != nil && err != io.EOF {
			return fmt.Errorf("error reading response body: %w", err)
		}
		total += length
		if spinner != nil && total-lastTotal > 1024*1024 {
			lastTotal = total
			spinner.UpdateText(fmt.Sprintf("%s (%d %%)", text, 100*total/size))
		}
		if length == 0 {
			break
		}
		if _, err = out.Write(buffer[:length]); err != nil {
			return fmt.Errorf("error writing to file: %w", err)
		}
	}

	// Check if the size matches, but only if the Content-Length header was present and valid
	if size > 0 && total != size {
		return fmt.Errorf("downloaded file size doesn't match expected size, got %d, expected %d", total, size)
	}

	if spinner != nil {
		spinner.UpdateText(fmt.Sprintf("%s (100 %%)", text))
	}

	return nil
}