Downloader.gd 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. extends Reference
  2. signal download_done(url)
  3. signal download_failed(url)
  4. func download(url):
  5. if fileExists(urlToFilePath(url)):
  6. emit_signal("download_done", url)
  7. return
  8. var use_ssl = false
  9. if "https" in url:
  10. use_ssl = true
  11. var splitUrl = url.split("/")
  12. var host = splitUrl[2]
  13. splitUrl.remove(0)
  14. splitUrl.remove(0)
  15. splitUrl.remove(0)
  16. var uri = "/"+splitUrl.join("/")
  17. var err = 0
  18. var http = HTTPClient.new() # Create the Client.
  19. err = http.connect_to_host(host, -1, use_ssl) # Connect to host/port.
  20. assert(err == OK) # Make sure connection was OK.
  21. # Wait until resolved and connected.
  22. while http.get_status() == HTTPClient.STATUS_CONNECTING or http.get_status() == HTTPClient.STATUS_RESOLVING:
  23. http.poll()
  24. print("Connecting...")
  25. OS.delay_msec(500)
  26. assert(http.get_status() == HTTPClient.STATUS_CONNECTED) # Could not connect
  27. # Some headers
  28. var headers = [
  29. "User-Agent: Pirulo/1.0 (Godot)",
  30. "Accept: */*"
  31. ]
  32. err = http.request(HTTPClient.METHOD_GET, uri, headers) # Request a page from the site (this one was chunked..)
  33. assert(err == OK) # Make sure all is OK.
  34. while http.get_status() == HTTPClient.STATUS_REQUESTING:
  35. # Keep polling for as long as the request is being processed.
  36. http.poll()
  37. print("Requesting...")
  38. if not OS.has_feature("web"):
  39. OS.delay_msec(500)
  40. else:
  41. # Synchronous HTTP requests are not supported on the web,
  42. # so wait for the next main loop iteration.
  43. yield(Engine.get_main_loop(), "idle_frame")
  44. assert(http.get_status() == HTTPClient.STATUS_BODY or http.get_status() == HTTPClient.STATUS_CONNECTED) # Make sure request finished well.
  45. print("response? ", http.has_response()) # Site might not have a response.
  46. if http.has_response():
  47. # If there is a response...
  48. headers = http.get_response_headers_as_dictionary() # Get response headers.
  49. print("code: ", http.get_response_code()) # Show response code.
  50. print("**headers:\\n", headers) # Show headers.
  51. # Getting the HTTP Body
  52. if http.is_response_chunked():
  53. # Does it use chunks?
  54. print("Response is Chunked!")
  55. else:
  56. # Or just plain Content-Length
  57. var bl = http.get_response_body_length()
  58. print("Response Length: ", bl)
  59. # This method works for both anyway
  60. var rb = PoolByteArray() # Array that will hold the data.
  61. while http.get_status() == HTTPClient.STATUS_BODY:
  62. # While there is body left to be read
  63. http.poll()
  64. var chunk = http.read_response_body_chunk() # Get a chunk.
  65. if chunk.size() == 0:
  66. # Got nothing, wait for buffers to fill a bit.
  67. OS.delay_usec(1000)
  68. else:
  69. rb = rb + chunk # Append to read buffer.
  70. # Done!
  71. var filePath = urlToFilePath(url)
  72. print("bytes got: ", rb.size())
  73. save_to_file(filePath, rb)
  74. print("file \"", filePath,"\" saved")
  75. http.close()
  76. emit_signal("download_done", url)
  77. func save_to_file(filePath, outBytes):
  78. createParentDirs(filePath)
  79. var dat_out = File.new()
  80. dat_out.open(filePath, File.WRITE)
  81. dat_out.store_buffer(outBytes)
  82. dat_out.close()
  83. func urlToFilePath(queryurl):
  84. var filePath = queryurl.replace("https://", "").replace("http://", "").rstrip("/")
  85. return "user://"+filePath
  86. func getBaseUrl(queryurl):
  87. var baseUrl = queryurl.split("/")
  88. baseUrl.remove(len(baseUrl)-1)
  89. baseUrl = baseUrl.join("/")
  90. return baseUrl
  91. func fileExists(filePath):
  92. var file = File.new()
  93. var err = file.open(filePath, file.READ)
  94. file.close()
  95. if err == OK:
  96. return true
  97. else:
  98. return false
  99. func createParentDirs(filePath):
  100. var splittedFileName = filePath.split("/")
  101. splittedFileName.remove(0)
  102. splittedFileName.remove(0)
  103. print(splittedFileName)
  104. var created = ""
  105. print("creating parent dirs")
  106. var x = 0
  107. for dir in splittedFileName:
  108. if x >= (len(splittedFileName)-1):
  109. break
  110. print("creating: "+"user://"+created+dir)
  111. var newdir = Directory.new()
  112. newdir.open("user://"+created)
  113. if newdir.dir_exists(dir):
  114. print("user://"+created+dir+" already exists")
  115. created = created+dir+"/"
  116. x += 1
  117. continue
  118. newdir.make_dir(dir)
  119. created = created+dir+"/"
  120. x += 1