package kemonoapi import ( "context" "fmt" "io" "strconv" "time" ) type fileInfo struct { URL string Length int64 ContentType string LastModified time.Time } func (c *Client) HeadFile(ctx context.Context, url string) (*fileInfo, error) { resp, err := c.client.R().SetContext(ctx).Head(url) if err != nil { return nil, fmt.Errorf("failed to download url %s: %w", url, err) } loc := resp.Header().Get("Location") if loc != "" { return c.HeadFile(ctx, loc) } length, err := strconv.ParseInt(resp.Header().Get("Content-Length"), 10, 64) if err != nil { return nil, fmt.Errorf("failed to parse Content-Length header: %w", err) } lastModified, err := time.Parse(time.RFC1123, resp.Header().Get("Last-Modified")) if err != nil { return nil, fmt.Errorf("failed to parse Last-Modified header: %w", err) } contentType := resp.Header().Get("Content-Type") return &fileInfo{ URL: url, Length: length, ContentType: contentType, LastModified: lastModified, }, nil } func (c *Client) DownloadFile(ctx context.Context, out io.Writer, url string) error { resp, err := c.client.R().SetContext(ctx).SetDoNotParseResponse(true).Get(url) if err != nil { return fmt.Errorf("failed to download url %s: %w", url, err) } body := resp.RawBody() defer body.Close() _, err = io.Copy(out, body) if err != nil { return fmt.Errorf("failed to download url %s: %w", url, err) } return nil }