Initial
This commit is contained in:
109
main.go
Normal file
109
main.go
Normal 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
|
||||
}
|
Reference in New Issue
Block a user