The first thing I would suggest is, to never do anything with the result without checking it first or …
if request.status == Sketchup::Http::STATUS_SUCCESS
# okay to read body here
else
# see what went wrong
puts "Request status: #{get_status(request.status)}"
puts "Response HTTP status: #{response.status_code}"
end
def get_status(status)
case status
when Sketchup::Http::STATUS_UNKNOWN
"Unknown"
when Sketchup::Http::STATUS_SUCCESS
"Success"
when Sketchup::Http::STATUS_PENDING
"Pending"
when Sketchup::Http::STATUS_CANCELED
"Canceled"
when Sketchup::Http::STATUS_FAILED
"Failed"
else
"Unknown"
end
end
Other than this we could not try it without the URL to your file.
The following code works for me, except that the total in the progress is always -1 from googledrive.
Win10, SU2021.
UPDATED (2021-05-12): Used @request for a persistent reference (per Christina,) added in download callback conditional to test the total size and react accordingly; and fixed the declaration of the header hash.
There were texture files that would be in a subfolder that are not included.
When SketchUp starts the working directory path is set to user documents.
SO if no path is given in the get_file method call, this is where the file will be written.
module TestDownload
extend self
PATTERN ||= "Downloading: %d (%#.1f%%)"
def get_file(
url_file = 'https://drive.google.com/uc?export=download&id=1La2-3FIlDM8a9T4lhr8XU8NR1hTDV80W',
file_downloaded_name
)
@request = Sketchup::Http::Request.new(url_file)
@request.headers= { "origin"=>"*", "x-request-with"=>"*"}
@request.set_download_progress_callback do |current, total|
if total > 0
percentage = ((current / total.to_f)*100).round(1)
puts format(PATTERN, current, percentage)
else
puts "Downloading: #{current}"
end
end
@request.start do |request, response|
if request.status == Sketchup::Http::STATUS_SUCCESS
# Okay to read body here:
File.open( file_downloaded_name,"wb") do |file|
file.flock(File::LOCK_EX)
file.write(response.body)
end
end
# See results:
puts "Request status result is: #{get_status(request.status)}"
puts "Response HTTP status (200 is success): #{response.status_code}"
# puts "body: #{response.body}" ## TOO BIG !
UI.start_timer(3.0,false) { @request = nil }
end
end ###
def get_status(status)
case status
when Sketchup::Http::STATUS_UNKNOWN
"Unknown"
when Sketchup::Http::STATUS_SUCCESS
"Success"
when Sketchup::Http::STATUS_PENDING
"Pending"
when Sketchup::Http::STATUS_CANCELED
"Canceled"
when Sketchup::Http::STATUS_FAILED
"Failed"
else
"Unknown"
end
end ###
end
Some servers do not send a total size for the resource being downloaded.
If this is the case, the total will not be more than zero (and usually == -1.)
So you can only calculate the percentage when the total is supplied.
Ex:
pattern = "Downloading: %d (%#.1f%%)"
request.set_download_progress_callback do |current, total|
if total > 0
percentage = ((current / total.to_f)*100).round(1)
puts format(pattern, current, percentage)
else
puts "Downloading: #{current}"
end
end
There is also a means in HTTP requests to ask the server ahead of time what size a resource is going to be. Not all servers will return the value. In this case the request is a HEAD type.
We had a similar issue. But it turns out it never occurs when the Ruby console is closed.
In our case, printing the download progress to the console made it stop randomly.
This might be related to garbage collection. Try assigning the request to an instance variable to make sure its kept alive, and the download may finish.