mirror of
https://github.com/fog/fog.git
synced 2022-11-09 13:51:43 -05:00
Stream data for S3 get/put object
This commit is contained in:
parent
09e952b665
commit
23ae9584a1
5 changed files with 47 additions and 16 deletions
|
@ -23,7 +23,7 @@ unless Fog.mocking?
|
||||||
# * 'Content-Type'<~String> - MIME type of object
|
# * 'Content-Type'<~String> - MIME type of object
|
||||||
# * 'ETag'<~String> - Etag of object
|
# * 'ETag'<~String> - Etag of object
|
||||||
# * 'Last-Modified'<~String> - Last modified timestamp for object
|
# * 'Last-Modified'<~String> - Last modified timestamp for object
|
||||||
def get_object(bucket_name, object_name, options = {})
|
def get_object(bucket_name, object_name, options = {}, &block)
|
||||||
unless bucket_name
|
unless bucket_name
|
||||||
raise ArgumentError.new('bucket_name is required')
|
raise ArgumentError.new('bucket_name is required')
|
||||||
end
|
end
|
||||||
|
@ -39,7 +39,8 @@ unless Fog.mocking?
|
||||||
:headers => headers,
|
:headers => headers,
|
||||||
:host => "#{bucket_name}.#{@host}",
|
:host => "#{bucket_name}.#{@host}",
|
||||||
:method => 'GET',
|
:method => 'GET',
|
||||||
:path => object_name
|
:path => object_name,
|
||||||
|
:block => block
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ unless Fog.mocking?
|
||||||
# ==== Parameters
|
# ==== Parameters
|
||||||
# * bucket_name<~String> - Name of bucket to create object in
|
# * bucket_name<~String> - Name of bucket to create object in
|
||||||
# * object_name<~String> - Name of object to create
|
# * object_name<~String> - Name of object to create
|
||||||
# * object<~String> - File to create object from
|
# * data<~File> - File or String to create object from
|
||||||
# * options<~Hash>:
|
# * options<~Hash>:
|
||||||
# * 'Cache-Control'<~String> - Caching behaviour
|
# * 'Cache-Control'<~String> - Caching behaviour
|
||||||
# * 'Content-Disposition'<~String> - Presentational information for the object
|
# * 'Content-Disposition'<~String> - Presentational information for the object
|
||||||
|
|
|
@ -87,20 +87,18 @@ module Fog
|
||||||
:headers => {}
|
:headers => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if data.respond_to?(:path)
|
if data.is_a?(String)
|
||||||
|
metadata[:body] = data
|
||||||
|
metadata[:headers]['Content-Length'] = metadata[:body].size.to_s
|
||||||
|
else
|
||||||
filename = File.basename(data.path)
|
filename = File.basename(data.path)
|
||||||
unless (mime_types = MIME::Types.of(filename)).empty?
|
unless (mime_types = MIME::Types.of(filename)).empty?
|
||||||
metadata[:headers]['Content-Type'] = mime_types.first.content_type
|
metadata[:headers]['Content-Type'] = mime_types.first.content_type
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
if data.respond_to?(:read)
|
|
||||||
metadata[:body] = data.read
|
metadata[:body] = data.read
|
||||||
else
|
metadata[:headers]['Content-Length'] = File.size(data.path)
|
||||||
metadata[:body] = data
|
|
||||||
end
|
end
|
||||||
metadata[:headers]['Content-Length'] = metadata[:body].size.to_s
|
# metadata[:headers]['Content-MD5'] = Base64.encode64(Digest::MD5.digest(metadata[:body])).strip
|
||||||
metadata[:headers]['Content-MD5'] = Base64.encode64(Digest::MD5.digest(metadata[:body])).strip
|
|
||||||
metadata
|
metadata
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -143,6 +141,7 @@ DATA
|
||||||
params[:headers]['Authorization'] = "AWS #{@aws_access_key_id}:#{signature}"
|
params[:headers]['Authorization'] = "AWS #{@aws_access_key_id}:#{signature}"
|
||||||
|
|
||||||
response = @connection.request({
|
response = @connection.request({
|
||||||
|
:block => params[:block],
|
||||||
:body => params[:body],
|
:body => params[:body],
|
||||||
:expects => params[:expects],
|
:expects => params[:expects],
|
||||||
:headers => params[:headers],
|
:headers => params[:headers],
|
||||||
|
|
|
@ -34,15 +34,26 @@ unless Fog.mocking?
|
||||||
request = "#{params[:method]} #{params[:path]} HTTP/1.1\r\n"
|
request = "#{params[:method]} #{params[:path]} HTTP/1.1\r\n"
|
||||||
params[:headers] ||= {}
|
params[:headers] ||= {}
|
||||||
params[:headers]['Host'] = params[:host]
|
params[:headers]['Host'] = params[:host]
|
||||||
if params[:body]
|
if params[:body] && !params[:headers]['Content-Length']
|
||||||
params[:headers]['Content-Length'] = params[:body].length
|
params[:headers]['Content-Length'] = params[:body].length
|
||||||
end
|
end
|
||||||
for key, value in params[:headers]
|
for key, value in params[:headers]
|
||||||
request << "#{key}: #{value}\r\n"
|
request << "#{key}: #{value}\r\n"
|
||||||
end
|
end
|
||||||
request << "\r\n#{params[:body]}"
|
request << "\r\n"
|
||||||
@connection.write(request)
|
@connection.write(request)
|
||||||
|
|
||||||
|
if params[:body]
|
||||||
|
if params[:body].is_a?(String)
|
||||||
|
body = StringIO.new(params[:body])
|
||||||
|
else
|
||||||
|
body = params[:body]
|
||||||
|
end
|
||||||
|
while chunk = body.read(1048576) # 1 megabyte
|
||||||
|
@connection.write(chunk)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
response = Fog::Response.new
|
response = Fog::Response.new
|
||||||
response.request = params
|
response.request = params
|
||||||
response.status = @connection.readline[9..11].to_i
|
response.status = @connection.readline[9..11].to_i
|
||||||
|
@ -65,19 +76,30 @@ unless Fog.mocking?
|
||||||
parser = params[:parser]
|
parser = params[:parser]
|
||||||
end
|
end
|
||||||
body = Nokogiri::XML::SAX::PushParser.new(parser)
|
body = Nokogiri::XML::SAX::PushParser.new(parser)
|
||||||
|
elsif params[:block]
|
||||||
|
body = nil
|
||||||
else
|
else
|
||||||
body = ''
|
body = ''
|
||||||
end
|
end
|
||||||
|
|
||||||
unless params[:method] == 'HEAD'
|
unless params[:method] == 'HEAD'
|
||||||
if response.headers['Content-Length']
|
if response.headers['Content-Length']
|
||||||
body << @connection.read(response.headers['Content-Length'].to_i)
|
content = @connection.read(response.headers['Content-Length'].to_i)
|
||||||
|
unless params[:block]
|
||||||
|
body << content
|
||||||
|
else
|
||||||
|
params[:block].call(content)
|
||||||
|
end
|
||||||
elsif response.headers['Transfer-Encoding'] == 'chunked'
|
elsif response.headers['Transfer-Encoding'] == 'chunked'
|
||||||
while true
|
while true
|
||||||
# 2 == "/r/n".length
|
# 2 == "/r/n".length
|
||||||
chunk_size = @connection.readline.chomp!.to_i(16) + 2
|
chunk_size = @connection.readline.chomp!.to_i(16) + 2
|
||||||
chunk = @connection.read(chunk_size)
|
chunk = @connection.read(chunk_size)[0...-2]
|
||||||
body << chunk[0...-2]
|
unless params[:block]
|
||||||
|
body << chunk
|
||||||
|
else
|
||||||
|
params[:block].call(chunk)
|
||||||
|
end
|
||||||
if chunk_size == 2
|
if chunk_size == 2
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
|
@ -26,6 +26,15 @@ describe 'S3.get_object' do
|
||||||
actual.headers['Last-Modified'].should be_a(String)
|
actual.headers['Last-Modified'].should be_a(String)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'should return chunks with optional block' do
|
||||||
|
file = File.open(File.dirname(__FILE__) + '/../../../lorem.txt', 'r')
|
||||||
|
data = ''
|
||||||
|
s3.get_object('foggetobject', 'fog_get_object') do |chunk|
|
||||||
|
data << chunk
|
||||||
|
end
|
||||||
|
data.should == file.read
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
describe 'failure' do
|
describe 'failure' do
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue