Files
flatrender/services/node-agent/internal/runner/download.go
T

83 lines
2.1 KiB
Go
Raw Normal View History

// download.go fetches a remote file (presigned MinIO URL or any HTTP URL) and
// saves it to a local path. Uses stdlib only — no external HTTP client needed.
package runner
import (
"context"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
)
// DownloadFile fetches the resource at rawURL and writes it to destPath,
// creating parent directories as needed. Returns the number of bytes written.
func DownloadFile(ctx context.Context, rawURL, destPath string) (int64, error) {
if err := os.MkdirAll(filepath.Dir(destPath), 0o755); err != nil {
return 0, fmt.Errorf("mkdir: %w", err)
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, rawURL, nil)
if err != nil {
return 0, fmt.Errorf("new request: %w", err)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return 0, fmt.Errorf("GET: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return 0, fmt.Errorf("server returned %d", resp.StatusCode)
}
f, err := os.Create(destPath)
if err != nil {
return 0, fmt.Errorf("create file: %w", err)
}
defer f.Close()
n, err := io.Copy(f, resp.Body)
if err != nil {
return 0, fmt.Errorf("write: %w", err)
}
return n, nil
}
// UploadFile PUTs a local file to a presigned MinIO/S3 URL.
// MinIO presigned PUT expects the raw bytes in the request body with
// Content-Type application/octet-stream.
func UploadFile(ctx context.Context, rawURL, filePath string) (int64, error) {
f, err := os.Open(filePath)
if err != nil {
return 0, fmt.Errorf("open: %w", err)
}
defer f.Close()
stat, err := f.Stat()
if err != nil {
return 0, fmt.Errorf("stat: %w", err)
}
req, err := http.NewRequestWithContext(ctx, http.MethodPut, rawURL, f)
if err != nil {
return 0, fmt.Errorf("new request: %w", err)
}
req.ContentLength = stat.Size()
req.Header.Set("Content-Type", "application/octet-stream")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return 0, fmt.Errorf("PUT: %w", err)
}
defer resp.Body.Close()
// MinIO returns 200 on successful PUT of presigned objects
if resp.StatusCode >= 300 {
return 0, fmt.Errorf("upload server returned %d", resp.StatusCode)
}
return stat.Size(), nil
}