| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- package main
- import (
- "fmt"
- "io"
- "net/http"
- "os"
- "path/filepath"
- "sync"
- "time"
- )
- func downloadTile(z, x, y int, wg *sync.WaitGroup, ch chan string, sem chan struct{}) {
- defer wg.Done()
- defer func() { <-sem }() // Release the semaphore slot
- client := &http.Client{}
- // Create a new request to the OpenStreetMap tile URL
- url := fmt.Sprintf("https://tile.openstreetmap.org/%d/%d/%d.png", z, x, y)
- req, err := http.NewRequest("GET", url, nil)
- if err != nil {
- ch <- fmt.Sprintf("Error creating request: %v", err)
- return
- }
- // Set the User-Agent header
- req.Header.Set("User-Agent", "MyTileDownloader/1.0")
- // Make the request
- response, err := client.Do(req)
- if err != nil {
- ch <- fmt.Sprintf("Error making request: %v", err)
- return
- }
- defer response.Body.Close()
- if response.StatusCode == http.StatusNotFound {
- ch <- fmt.Sprintf("Tile %d/%d/%d not found (404)\n", z, x, y)
- return
- }
- if response.StatusCode != http.StatusOK {
- ch <- fmt.Sprintf("Failed to download tile %d/%d/%d: %s\n", z, x, y, response.Status)
- return
- }
- // Create the destination directory
- tilePath := filepath.Join(fmt.Sprintf("%d", z), fmt.Sprintf("%d", x), fmt.Sprintf("%d", y)+".png")
- os.MkdirAll(filepath.Dir(tilePath), os.ModePerm)
- outFile, err := os.Create(tilePath)
- if err != nil {
- ch <- fmt.Sprintf("Error creating file: %v", err)
- return
- }
- defer outFile.Close()
- _, err = io.Copy(outFile, response.Body)
- if err != nil {
- ch <- fmt.Sprintf("Error saving file: %v", err)
- return
- }
- ch <- fmt.Sprintf("Downloaded tile: z %d, x %d, y %d\n", z, x, y)
- }
- func main() {
- var wg sync.WaitGroup
- ch := make(chan string)
- sem := make(chan struct{}, 1500) // Semaphore with 1500 slots
- // Goroutine to print messages from the channel
- go func() {
- for msg := range ch {
- fmt.Print(msg)
- }
- }()
- i := 0
- j := 0
- for z := 10; z < 19; z++ {
- finz := 1 << z // equivalent to 2^z
- for x := i; x < finz; x++ {
- for y := j; y < finz; y++ {
- wg.Add(1)
- sem <- struct{}{} // Acquire a semaphore slot
- go downloadTile(z, x, y, &wg, ch, sem)
- time.Sleep(15 * time.Millisecond) // Pause between starting new goroutines
- }
- j = 0
- i = 0
- }
- }
- wg.Wait()
- close(ch)
- }
|