aides-uploader/main.go
2024-11-29 17:32:44 +03:00

183 lines
4.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"bytes"
"flag"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
"path/filepath"
"strings"
)
type Configuration struct {
ServerURL string
Repo string
TaskID string
Token string
FilePatterns []string
Files []string
}
func parseFlags() Configuration {
var cfg Configuration
flag.StringVar(&cfg.ServerURL, "url", "http://localhost:9999", "Базовый URL сервера загрузки")
flag.StringVar(&cfg.Repo, "repo", "", "Название репозитория (обязательно)")
flag.StringVar(&cfg.TaskID, "task", "", "ID задачи (обязательно)")
flag.StringVar(&cfg.Token, "token", "", "Токен авторизации (обязательно)")
files := flag.String("files", "", "Список путей к файлам или паттернов (разделены запятой) для загрузки (обязательно)")
flag.Parse()
missing := false
if cfg.Repo == "" {
fmt.Println("Ошибка: -repo является обязательным")
missing = true
}
if cfg.TaskID == "" {
fmt.Println("Ошибка: -task является обязательным")
missing = true
}
if cfg.Token == "" {
fmt.Println("Ошибка: -token является обязательным")
missing = true
}
if *files == "" {
fmt.Println("Ошибка: -files является обязательным")
missing = true
}
if missing {
flag.Usage()
os.Exit(1)
}
cfg.FilePatterns = splitAndTrim(*files, ",")
var allFiles []string
for _, pattern := range cfg.FilePatterns {
matches, err := filepath.Glob(pattern)
if err != nil {
fmt.Fprintf(os.Stderr, "Неверный паттерн glob '%s': %v\n", pattern, err)
continue
}
if len(matches) == 0 {
fmt.Fprintf(os.Stderr, "Предупреждение: Паттерн '%s' не совпадает ни с одним файлом\n", pattern)
continue
}
allFiles = append(allFiles, matches...)
}
cfg.Files = unique(allFiles)
if len(cfg.Files) == 0 {
fmt.Println("Ошибка: Не найдено файлов для загрузки после обработки паттернов")
os.Exit(1)
}
return cfg
}
func splitAndTrim(s, sep string) []string {
parts := strings.Split(s, sep)
var trimmed []string
for _, part := range parts {
part = strings.TrimSpace(part)
if part != "" {
trimmed = append(trimmed, part)
}
}
return trimmed
}
func unique(input []string) []string {
seen := make(map[string]struct{})
var result []string
for _, item := range input {
if _, exists := seen[item]; !exists {
seen[item] = struct{}{}
result = append(result, item)
}
}
return result
}
func createMultipartRequest(url string, files []string, token string) (*http.Request, error) {
var buf bytes.Buffer
writer := multipart.NewWriter(&buf)
for _, filePath := range files {
file, err := os.Open(filePath)
if err != nil {
return nil, fmt.Errorf("не удалось открыть файл %s: %w", filePath, err)
}
defer file.Close()
part, err := writer.CreateFormFile("files", filepath.Base(filePath))
if err != nil {
return nil, fmt.Errorf("не удалось создать поле формы для файла %s: %w", filePath, err)
}
_, err = io.Copy(part, file)
if err != nil {
return nil, fmt.Errorf("не удалось скопировать содержимое файла %s: %w", filePath, err)
}
}
err := writer.Close()
if err != nil {
return nil, fmt.Errorf("не удалось закрыть multipart писатель: %w", err)
}
req, err := http.NewRequest("POST", url, &buf)
if err != nil {
return nil, fmt.Errorf("не удалось создать HTTP-запрос: %w", err)
}
req.Header.Set("Content-Type", writer.FormDataContentType())
req.Header.Set("Authorization", "Bearer "+token)
return req, nil
}
func uploadFiles(cfg Configuration) error {
uploadURL := fmt.Sprintf("%s/upload/%s/task/%s", strings.TrimRight(cfg.ServerURL, "/"), cfg.Repo, cfg.TaskID)
req, err := createMultipartRequest(uploadURL, cfg.Files, cfg.Token)
if err != nil {
return fmt.Errorf("не удалось создать multipart-запрос: %w", err)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("не удалось выполнить HTTP-запрос: %w", err)
}
defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("не удалось прочитать тело ответа: %w", err)
}
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("загрузка не удалась с кодом %d: %s", resp.StatusCode, string(respBody))
}
fmt.Println("Загрузка успешна:")
fmt.Println(string(respBody))
return nil
}
func main() {
cfg := parseFlags()
err := uploadFiles(cfg)
if err != nil {
fmt.Fprintf(os.Stderr, "Ошибка: %v\n", err)
os.Exit(1)
}
}