Download file stop suddenly

I try to download large file on my own server in sketchup but the download crash without any error’s messages.
My code for downloading

request = Sketchup::Http::Request.new(url_file);
request.headers= {:"origin"=>"*",:"x-request-with"=>"*"}

request.set_download_progress_callback do |current, total|
    puts "download current: #{current}/ #{total}"
end

request.start do |request, response|
    File.open("#{file_downloaded_name}","wb") do |file|
        file.flock(File::LOCK_EX)
        file.write(response.body)

    end
    puts response.status
    puts "body: #{response.body}"
end

The ruby console

Here you have the file i testing
test_import_dae.dae (10.5 MB)

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.

Here i create direct link to access file

https://drive.google.com/uc?export=download&id=1La2-3FIlDM8a9T4lhr8XU8NR1hTDV80W

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.

image

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

@DanRathbun your code works fine for me but sometimes i get the same issue mentionned above.

@DanRathbun I tested your code 10 times, and I have a 40% success rate, (i create folder for images)
and i always the same issue, another idea?

Well what is the error code ? Any? or it just locks up ?

Is it with ALL servers ? … or only your server ?

What about using default HTTP headers ?

it just locks up

Is with ALL servers

I think my issue is due to headers
I found another solution with the library ‘open-uri’
This following code works very well

require 'open-uri'
....
URI.open("#{url_file}","origin"=>"*","x-request-with"=>"*") {|f|
    File.open("#{file_downloaded_name}","wb") do |file|
        file.write(f.read)
    end

    puts "It works"
}

one last thing, how to get the download percentage during the operation?

Then please file a formal issue in the official API Issue Tracker:
Issues · SketchUp/api-issue-tracker · GitHub

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

REF:


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.

REF:

Open API Issue:

Another forum topic on this subject:

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.

You should try with the console closed.

1 Like

It sounds silly (laff) but there have been numerous issues over the years with the console that I can believe it.

Perhaps send the output to SketchUp’s status bar instead of puts ?

Yes, I will try to formalize as best I can before posting on the branch

I haven’t tried it yet

Yeah I will do that

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.

1 Like

@ene_su True that Christina.

I also just noticed that the request header hash was wrong.
There were colons preceding the string keys. Ie …

    request.headers= {:"origin"=>"*",:"x-request-with"=>"*"}

…should have been simply:

    request.headers= { "origin"=>"*", "x-request-with"=>"*"}

I’ve updated the test example above, adding in the conditional for the progress callback from post 9.