使用 rest-client 将文件下载到磁盘而不先将其全部加载到内存中
Using rest-client to download a file to disk without loading it all in memory first
我正在使用 rest-client 下载大页面(大约 1.5 GB)。检索到的值存储在内存中而不是保存到文件中。结果我的程序崩溃 failed to allocate memory (NoMemoryError)
.
但是这些数据没有必要保存在内存中,甚至可以直接保存到磁盘中。
我在 https://github.com/rest-client/rest-client Unfortunately after reading http://www.rubydoc.info/gems/rest-client/1.7.3/RestClient/Request 上找到了 "You can: (...) manually handle the response (e.g. to operate on it as a stream rather than reading it all into memory) See RestClient::Request's documentation for more information." 我不知道它是如何完成的。
我也知道我可能会使用其他库 (Using WWW:Mechanize to download a file to disk without loading it all in memory first),但我的程序已经在使用 rest-client。
简化代码:
data = RestClient::Request.execute(:method => :get, :url => url, :timeout => 3600)
file = File.new(filename, 'w')
file.write data
file.close
我原来的回答提倡将块传递给 RestClient::Request#execute
,但这只会在读取完整响应后才将数据传递给块。从而使练习变得毫无价值。这是正确的做法:
File.open('/tmp/foo.iso', 'w') {|f|
block = proc { |response|
response.read_body do |chunk|
puts "Working on response"
f.write chunk
end
}
RestClient::Request.new(method: :get, url: 'http://mirror.pnl.gov/releases/xenial/ubuntu-16.04-server-amd64.iso', block_response: block).execute
}
来自相关rest-client project issue.
注意: 重定向在这种模式下不起作用,您也会丢失 HTTP 退出状态、cookie、headers 等。希望有一天这会得到修复.
另一种方法是使用raw_response
。这会直接保存到文件中,通常在 /tmp
中,并且可以毫无问题地处理重定向。
参见 Streaming Responses。这是他们的例子:
>> raw = RestClient::Request.execute(
method: :get,
url: 'http://releases.ubuntu.com/16.04.2/ubuntu-16.04.2-desktop-amd64.iso',
raw_response: true)
=> <RestClient::RawResponse @code=200, @file=#<Tempfile:/tmp/rest-client.20170522-5346-1pptjm1>, @request=<RestClient::Request @method="get", @url="http://releases.ubuntu.com/16.04.2/ubuntu-16.04.2-desktop-amd64.iso">>
>> raw.file.size
=> 1554186240
>> raw.file.path
=> "/tmp/rest-client.20170522-5346-1pptjm1"
我正在使用 rest-client 下载大页面(大约 1.5 GB)。检索到的值存储在内存中而不是保存到文件中。结果我的程序崩溃 failed to allocate memory (NoMemoryError)
.
但是这些数据没有必要保存在内存中,甚至可以直接保存到磁盘中。
我在 https://github.com/rest-client/rest-client Unfortunately after reading http://www.rubydoc.info/gems/rest-client/1.7.3/RestClient/Request 上找到了 "You can: (...) manually handle the response (e.g. to operate on it as a stream rather than reading it all into memory) See RestClient::Request's documentation for more information." 我不知道它是如何完成的。
我也知道我可能会使用其他库 (Using WWW:Mechanize to download a file to disk without loading it all in memory first),但我的程序已经在使用 rest-client。
简化代码:
data = RestClient::Request.execute(:method => :get, :url => url, :timeout => 3600)
file = File.new(filename, 'w')
file.write data
file.close
我原来的回答提倡将块传递给 RestClient::Request#execute
,但这只会在读取完整响应后才将数据传递给块。从而使练习变得毫无价值。这是正确的做法:
File.open('/tmp/foo.iso', 'w') {|f|
block = proc { |response|
response.read_body do |chunk|
puts "Working on response"
f.write chunk
end
}
RestClient::Request.new(method: :get, url: 'http://mirror.pnl.gov/releases/xenial/ubuntu-16.04-server-amd64.iso', block_response: block).execute
}
来自相关rest-client project issue.
注意: 重定向在这种模式下不起作用,您也会丢失 HTTP 退出状态、cookie、headers 等。希望有一天这会得到修复.
另一种方法是使用raw_response
。这会直接保存到文件中,通常在 /tmp
中,并且可以毫无问题地处理重定向。
参见 Streaming Responses。这是他们的例子:
>> raw = RestClient::Request.execute(
method: :get,
url: 'http://releases.ubuntu.com/16.04.2/ubuntu-16.04.2-desktop-amd64.iso',
raw_response: true)
=> <RestClient::RawResponse @code=200, @file=#<Tempfile:/tmp/rest-client.20170522-5346-1pptjm1>, @request=<RestClient::Request @method="get", @url="http://releases.ubuntu.com/16.04.2/ubuntu-16.04.2-desktop-amd64.iso">>
>> raw.file.size
=> 1554186240
>> raw.file.path
=> "/tmp/rest-client.20170522-5346-1pptjm1"