我正在使用net/http库调用read_body两次(IOError)。我正在努力下载文件并有效地使用http会话。寻求一些帮助或建议来解决我的问题。从我的调试消息中,当我记录响应代码readbody=true时,它就会出现。这就是为什么当我试着用块写大文件时,read_body会被读两次吗?
D, [2015-04-12T21:17:46.954928 #24741] DEBUG -- : #<Net::HTTPOK 200 OK readbody=true>
I, [2015-04-12T21:17:46.955060 #24741] INFO -- : file found at http://hidden:8080/job/project/1/maven-repository/repository/org/project/service/1/service-1.zip.md5
/usr/lib/ruby/2.2.0/net/http/response.rb:195:in `read_body': Net::HTTPOK#read_body called twice (IOError)
from ./deploy_application.rb:36:in `block in get_file'
from ./deploy_application.rb:35:in `open'
from ./deploy_application.rb:35:in `get_file'
from ./deploy_application.rb:59:in `block in <main>'
from ./deploy_application.rb:58:in `each'
from ./deploy_application.rb:58:in `<main>'require 'net/http'
require 'logger'
STAMP = Time.now.utc.to_i
@log = Logger.new(STDOUT)
# project , build, service remove variables above
project = "project"
build = "1"
service = "service"
version = "1"
BASE_URI = URI("http://hidden:8080/job/#{project}/#{build}/maven-repository/repository/org/#{service}/#{version}/")
# file pattern for application is zip / jar. Hopefully the lib in the zipfile is acceptable.
# example for module download /#{service}/#{version}.zip /#{service}/#{version}.zip.md5 /#{service}/#{version}.jar /#{service}/#{version}.jar.md5
def clean_exit(code)
# remove temp files on exit
end
def get_file(file)
puts BASE_URI
uri = URI.join(BASE_URI,file)
@log.debug(uri)
request = Net::HTTP::Get.new uri #.request_uri
@log.debug(request)
response = @http.request request
@log.debug(response)
case response
when Net::HTTPOK
size = 0
progress = 0
total = response.header["Content-Length"].to_i
@log.info("file found at #{uri}")
# need to handle file open error
Dir.mkdir "/tmp/#{STAMP}"
File.open "/tmp/#{STAMP}/#{file}", 'wb' do |io|
response.read_body do |chunk|
size += chunk.size
new_progress = (size * 100) / total
unless new_progress == progress
@log.info("\rDownloading %s (%3d%%) " % [file, new_progress])
end
progress = new_progress
io.write chunk
end
end
when 404
@log.error("maven repository file #{uri} not found")
exit 4
when 500...600
@log.error("error getting #{uri}, server returned #{response.code}")
exit 5
else
@log.error("unknown http response code #{response.code}")
end
end
@http = Net::HTTP.new(BASE_URI.host, BASE_URI.port)
files = [ "#{service}-#{version}.zip.md5", "#{service}-#{version}.jar", "#{service}-#{version}.jar.md5" ].each do |file| #"#{service}-#{version}.zip",
get_file(file)
end发布于 2015-04-13 05:20:45
编辑:修改后的答案!
当Net::HTTP#request被调用时,如果没有阻塞,就会先发制人地读取身体.文献资料还不清楚这一点,但它暗示,如果一个块被传递,就不会读取身体。
如果您想在不读取主体的情况下发出请求,则需要将一个块传递给请求调用,然后从请求调用中读取主体。也就是说,你想要这样的东西:
@http.request request do |response|
# ...
response.read_body do |chunk|
# ...
end
end在实施中可以清楚地看到这一点;如果给定块(来自#transport_request,从#request调用),则Response#reading_body将首先生成未读取的响应,然后无条件地读取正文。#request的块参数为您提供了在读取主体之前拦截响应的机会。
https://stackoverflow.com/questions/29598196
复制相似问题