lib/fakes3/file_store.rb in fakes3-0.2.0 vs lib/fakes3/file_store.rb in fakes3-0.2.1
- old
+ new
@@ -101,11 +101,11 @@
end
def object_metadata(bucket,object)
end
- def copy_object(src_bucket_name,src_name,dst_bucket_name,dst_name,request)
+ def copy_object(src_bucket_name, src_name, dst_bucket_name, dst_name, request)
src_root = File.join(@root,src_bucket_name,src_name,SHUCK_METADATA_DIR)
src_metadata_filename = File.join(src_root,"metadata")
src_metadata = YAML.load(File.open(src_metadata_filename,'rb').read)
src_content_filename = File.join(src_root,"content")
@@ -138,12 +138,12 @@
File.open(metadata,'w') do |f|
f << YAML::dump(metadata_struct)
end
end
- src_bucket = self.get_bucket(src_bucket_name)
- dst_bucket = self.get_bucket(dst_bucket_name)
+ src_bucket = get_bucket(src_bucket_name) || create_bucket(src_bucket_name)
+ dst_bucket = get_bucket(dst_bucket_name) || create_bucket(dst_bucket_name)
obj = S3Object.new
obj.name = dst_name
obj.md5 = src_metadata[:md5]
obj.content_type = src_metadata[:content_type]
@@ -153,41 +153,48 @@
src_obj = src_bucket.find(src_name)
dst_bucket.add(obj)
return obj
end
- def store_object(bucket,object_name,request)
+ def store_object(bucket, object_name, request)
+ filedata = ""
+
+ # TODO put a tmpfile here first and mv it over at the end
+ content_type = request.content_type || ""
+
+ match = content_type.match(/^multipart\/form-data; boundary=(.+)/)
+ boundary = match[1] if match
+ if boundary
+ boundary = WEBrick::HTTPUtils::dequote(boundary)
+ form_data = WEBrick::HTTPUtils::parse_form_data(request.body, boundary)
+
+ if form_data['file'] == nil or form_data['file'] == ""
+ raise WEBrick::HTTPStatus::BadRequest
+ end
+
+ filedata = form_data['file']
+ else
+ request.body { |chunk| filedata << chunk }
+ end
+
+ do_store_object(bucket, object_name, filedata, request)
+ end
+
+ def do_store_object(bucket, object_name, filedata, request)
begin
filename = File.join(@root,bucket.name,object_name)
FileUtils.mkdir_p(filename)
metadata_dir = File.join(filename,SHUCK_METADATA_DIR)
FileUtils.mkdir_p(metadata_dir)
- content = File.join(filename,SHUCK_METADATA_DIR,"content")
+ content = File.join(filename,SHUCK_METADATA_DIR,"content")
metadata = File.join(filename,SHUCK_METADATA_DIR,"metadata")
- # TODO put a tmpfile here first and mv it over at the end
+ File.open(content,'wb') { |f| f << filedata }
- match=request.content_type.match(/^multipart\/form-data; boundary=(.+)/)
- boundary = match[1] if match
- if boundary
- boundary = WEBrick::HTTPUtils::dequote(boundary)
- filedata = WEBrick::HTTPUtils::parse_form_data(request.body, boundary)
- raise HTTPStatus::BadRequest if filedata['file'].empty?
- File.open(content, 'wb') do |f|
- f << filedata['file']
- end
- else
- File.open(content,'wb') do |f|
- request.body do |chunk|
- f << chunk
- end
- end
- end
metadata_struct = create_metadata(content,request)
-
File.open(metadata,'w') do |f|
f << YAML::dump(metadata_struct)
end
obj = S3Object.new
@@ -204,10 +211,40 @@
$!.backtrace.each { |line| puts line }
return nil
end
end
+ def combine_object_parts(bucket, upload_id, object_name, parts, request)
+ upload_path = File.join(@root, bucket.name)
+ base_path = File.join(upload_path, "#{upload_id}_#{object_name}")
+
+ complete_file = ""
+ chunk = ""
+ part_paths = []
+
+ parts.sort_by { |part| part[:number] }.each do |part|
+ part_path = "#{base_path}_part#{part[:number]}"
+ content_path = File.join(part_path, SHUCK_METADATA_DIR, 'content')
+
+ File.open(content_path, 'rb') { |f| chunk = f.read }
+ etag = Digest::MD5.hexdigest(chunk)
+
+ raise new Error "invalid file chunk" unless part[:etag] == etag
+ complete_file << chunk
+ part_paths << part_path
+ end
+
+ object = do_store_object(bucket, object_name, complete_file, request)
+
+ # clean up parts
+ part_paths.each do |path|
+ FileUtils.remove_dir(path)
+ end
+
+ object
+ end
+
def delete_object(bucket,object_name,request)
begin
filename = File.join(@root,bucket.name,object_name)
FileUtils.rm_rf(filename)
object = bucket.find(object_name)
@@ -217,9 +254,10 @@
$!.backtrace.each { |line| puts line }
return nil
end
end
+ # TODO: abstract getting meta data from request.
def create_metadata(content,request)
metadata = {}
metadata[:md5] = Digest::MD5.file(content).hexdigest
metadata[:content_type] = request.header["content-type"].first
metadata[:size] = File.size(content)