send2gokapi/client.go

117 lines
2.9 KiB
Go
Raw Normal View History

2025-01-03 04:16:27 +00:00
package main
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"net/url"
"strconv"
"strings"
)
type gokapiClient struct {
httpClient *http.Client
host *url.URL
apiKey string
}
func newGokapiClient(host *url.URL, apiKey string) *gokapiClient {
return &gokapiClient{
httpClient: &http.Client{},
host: host,
apiKey: apiKey,
}
}
func (gc *gokapiClient) uploadChunk(ctx context.Context, fi uploadInfo, offset int64, data io.Reader) error {
var body bytes.Buffer
boundary, err := gc.prepUploadChunkBody(&body, fi, offset, data)
if err != nil {
return err
}
actionURL := gc.host.ResolveReference(&url.URL{Path: "/api/chunk/add"})
req, err := http.NewRequestWithContext(ctx, "POST", actionURL.String(), &body)
if err != nil {
return err
}
req.Header.Set("Accept", "application/json")
req.Header.Set("Apikey", gc.apiKey)
req.Header.Set("Content-Type", "multipart/form-data; boundary="+boundary)
resp, err := gc.httpClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("upload chunk failed with status code %d", resp.StatusCode)
}
return nil
}
func (gc *gokapiClient) finalizeChunk(ctx context.Context, fi uploadInfo) (UploadResponse, error) {
actionURL := gc.host.ResolveReference(&url.URL{Path: "/api/chunk/complete"})
formData := url.Values{}
formData.Set("uuid", fi.chunkID)
formData.Set("filename", fi.filename)
formData.Set("filesize", strconv.FormatInt(fi.totalSize, 10))
formData.Set("contenttype", fi.contentType)
formData.Set("allowedDownloads", strconv.Itoa(fi.allowedDownloads))
formData.Set("expiryDays", strconv.Itoa(fi.expiryDays))
formData.Set("password", fi.password)
req, err := http.NewRequestWithContext(ctx, "POST", actionURL.String(), strings.NewReader(formData.Encode()))
if err != nil {
return UploadResponse{}, err
}
req.Header.Set("Accept", "application/json")
req.Header.Set("Apikey", gc.apiKey)
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := gc.httpClient.Do(req)
if err != nil {
return UploadResponse{}, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return UploadResponse{}, fmt.Errorf("upload chunk finalization with status code %d", resp.StatusCode)
}
var r UploadResponse
if err := json.NewDecoder(resp.Body).Decode(&r); err != nil {
return UploadResponse{}, err
}
return r, nil
}
func (gc *gokapiClient) prepUploadChunkBody(w io.Writer, fi uploadInfo, offset int64, data io.Reader) (string, error) {
mw := multipart.NewWriter(w)
defer mw.Close()
mw.WriteField("uuid", fi.chunkID)
mw.WriteField("filesize", strconv.FormatInt(fi.totalSize, 10))
mw.WriteField("offset", strconv.FormatInt(offset, 10))
fileWriter, err := mw.CreateFormFile("file", fi.filename)
if err != nil {
return "", err
}
_, err = io.Copy(fileWriter, data)
if err != nil {
return "", err
}
return mw.Boundary(), nil
}