downloadOpenMapStreet.go 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. package main
  2. import (
  3. "fmt"
  4. "io"
  5. "net/http"
  6. "os"
  7. "path/filepath"
  8. "sync"
  9. "time"
  10. )
  11. func downloadTile(z, x, y int, wg *sync.WaitGroup, ch chan string, sem chan struct{}) {
  12. defer wg.Done()
  13. defer func() { <-sem }() // Release the semaphore slot
  14. client := &http.Client{}
  15. // Create a new request to the OpenStreetMap tile URL
  16. url := fmt.Sprintf("https://tile.openstreetmap.org/%d/%d/%d.png", z, x, y)
  17. req, err := http.NewRequest("GET", url, nil)
  18. if err != nil {
  19. ch <- fmt.Sprintf("Error creating request: %v", err)
  20. return
  21. }
  22. // Set the User-Agent header
  23. req.Header.Set("User-Agent", "MyTileDownloader/1.0")
  24. // Make the request
  25. response, err := client.Do(req)
  26. if err != nil {
  27. ch <- fmt.Sprintf("Error making request: %v", err)
  28. return
  29. }
  30. defer response.Body.Close()
  31. if response.StatusCode == http.StatusNotFound {
  32. ch <- fmt.Sprintf("Tile %d/%d/%d not found (404)\n", z, x, y)
  33. return
  34. }
  35. if response.StatusCode != http.StatusOK {
  36. ch <- fmt.Sprintf("Failed to download tile %d/%d/%d: %s\n", z, x, y, response.Status)
  37. return
  38. }
  39. // Create the destination directory
  40. tilePath := filepath.Join(fmt.Sprintf("%d", z), fmt.Sprintf("%d", x), fmt.Sprintf("%d", y)+".png")
  41. os.MkdirAll(filepath.Dir(tilePath), os.ModePerm)
  42. outFile, err := os.Create(tilePath)
  43. if err != nil {
  44. ch <- fmt.Sprintf("Error creating file: %v", err)
  45. return
  46. }
  47. defer outFile.Close()
  48. _, err = io.Copy(outFile, response.Body)
  49. if err != nil {
  50. ch <- fmt.Sprintf("Error saving file: %v", err)
  51. return
  52. }
  53. ch <- fmt.Sprintf("Downloaded tile: z %d, x %d, y %d\n", z, x, y)
  54. }
  55. func main() {
  56. var wg sync.WaitGroup
  57. ch := make(chan string)
  58. sem := make(chan struct{}, 1500) // Semaphore with 1500 slots
  59. // Goroutine to print messages from the channel
  60. go func() {
  61. for msg := range ch {
  62. fmt.Print(msg)
  63. }
  64. }()
  65. i := 0
  66. j := 0
  67. for z := 10; z < 19; z++ {
  68. finz := 1 << z // equivalent to 2^z
  69. for x := i; x < finz; x++ {
  70. for y := j; y < finz; y++ {
  71. wg.Add(1)
  72. sem <- struct{}{} // Acquire a semaphore slot
  73. go downloadTile(z, x, y, &wg, ch, sem)
  74. time.Sleep(15 * time.Millisecond) // Pause between starting new goroutines
  75. }
  76. j = 0
  77. i = 0
  78. }
  79. }
  80. wg.Wait()
  81. close(ch)
  82. }