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 }