package transfer import ( "fmt" "io" "net/http" "os" "path/filepath" "time" ) // UploadFile PUTs a local file to a presigned URL. func UploadFile(localPath, uploadURL string) error { file, err := os.Open(localPath) if err != nil { return err } defer file.Close() stat, err := file.Stat() if err != nil { return err } request, err := http.NewRequest(http.MethodPut, uploadURL, file) if err != nil { return err } request.ContentLength = stat.Size() request.Header.Set("Content-Type", "application/gzip") client := &http.Client{Timeout: 30 * time.Minute} response, err := client.Do(request) if err != nil { return err } defer response.Body.Close() if response.StatusCode < 200 || response.StatusCode >= 300 { body, _ := io.ReadAll(io.LimitReader(response.Body, 4096)) return fmt.Errorf("upload failed with status %d: %s", response.StatusCode, string(body)) } return nil } // DownloadFile GETs a remote file to a local path. func DownloadFile(downloadURL, localPath string) error { if err := os.MkdirAll(filepath.Dir(localPath), 0o755); err != nil { return err } client := &http.Client{Timeout: 30 * time.Minute} response, err := client.Get(downloadURL) if err != nil { return err } defer response.Body.Close() if response.StatusCode < 200 || response.StatusCode >= 300 { body, _ := io.ReadAll(io.LimitReader(response.Body, 4096)) return fmt.Errorf("download failed with status %d: %s", response.StatusCode, string(body)) } file, err := os.Create(localPath) if err != nil { return err } defer file.Close() _, err = io.Copy(file, response.Body) return err }