commit bb2af1a366155ecd1514516aea5123734bcfc5d2 Author: Anton Vakhrushev Date: Thu May 29 17:07:30 2025 +0300 Initial diff --git a/main.go b/main.go new file mode 100644 index 0000000..2b7d1f0 --- /dev/null +++ b/main.go @@ -0,0 +1,109 @@ +package main + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + "sync" + "time" +) + +func main() { + if len(os.Args) != 3 { + fmt.Println("Usage: program ") + os.Exit(1) + } + + jsonFile := os.Args[1] + outputDir := os.Args[2] + + // Создаем директорию для загрузок + if err := os.MkdirAll(outputDir, 0755); err != nil { + fmt.Printf("Error creating directory: %v\n", err) + os.Exit(1) + } + + // Читаем JSON файл + data, err := os.ReadFile(jsonFile) + if err != nil { + fmt.Printf("Error reading JSON file: %v\n", err) + os.Exit(1) + } + + // Парсим JSON в массив строк + var urls []string + if err := json.Unmarshal(data, &urls); err != nil { + fmt.Printf("Error parsing JSON: %v\n", err) + os.Exit(1) + } + + // Семафор для ограничения параллелизма + sem := make(chan struct{}, 5) + var wg sync.WaitGroup + + start := time.Now() + for i, url := range urls { + wg.Add(1) + sem <- struct{}{} // Занимаем слот + + go func(idx int, url string) { + defer wg.Done() + defer func() { <-sem }() // Освобождаем слот + + filename := filepath.Join(outputDir, fmt.Sprintf("image_%06d%s", idx, fileExtension(url))) + if err := downloadImage(url, filename); err != nil { + fmt.Printf("Error downloading %s: %v\n", url, err) + } else { + fmt.Printf("Downloaded %s -> %s\n", url, filename) + } + }(i, url) + } + + wg.Wait() + fmt.Printf("\nDownloaded %d images in %v\n", len(urls), time.Since(start)) +} + +// Определяем расширение файла по Content-Type +func fileExtension(url string) string { + contentTypes := map[string]string{ + "image/jpeg": ".jpg", + "image/png": ".png", + "image/gif": ".gif", + "image/webp": ".webp", + "image/svg+xml": ".svg", + } + + resp, err := http.Head(url) + if err == nil { + ct := resp.Header.Get("Content-Type") + if ext, ok := contentTypes[ct]; ok { + return ext + } + } + return ".bin" // расширение по умолчанию +} + +// Скачиваем и сохраняем изображение +func downloadImage(url, filename string) error { + resp, err := http.Get(url) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("HTTP error: %s", resp.Status) + } + + file, err := os.Create(filename) + if err != nil { + return err + } + defer file.Close() + + _, err = io.Copy(file, resp.Body) + return err +}