This commit is contained in:
2025-05-29 17:07:30 +03:00
commit bb2af1a366

109
main.go Normal file
View File

@@ -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 <json-file> <output-dir>")
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
}