lib/cloudinary/uploader.rb in cloudinary-1.0.69 vs lib/cloudinary/uploader.rb in cloudinary-1.0.70
- old
+ new
@@ -1,97 +1,108 @@
-# Copyright Cloudinary
-require 'rest_client'
-require 'json'
-
-class Cloudinary::Uploader
-
- def self.build_eager(eager)
- return nil if eager.nil?
- Cloudinary::Utils.build_array(eager).map do
- |transformation, format|
- transformation = transformation.clone
- format = transformation.delete(:format) || format
- [Cloudinary::Utils.generate_transformation_string(transformation), format].compact.join("/")
- end.join("|")
- end
-
- def self.build_upload_params(options)
- params = {:timestamp=>Time.now.to_i,
- :transformation => Cloudinary::Utils.generate_transformation_string(options.clone),
- :public_id=> options[:public_id],
- :callback=> options[:callback],
- :format=>options[:format],
- :type=>options[:type],
- :backup=>Cloudinary::Utils.as_safe_bool(options[:backup]),
- :faces=>Cloudinary::Utils.as_safe_bool(options[:faces]),
- :exif=>Cloudinary::Utils.as_safe_bool(options[:exif]),
- :colors=>Cloudinary::Utils.as_safe_bool(options[:colors]),
- :image_metadata=>Cloudinary::Utils.as_safe_bool(options[:image_metadata]),
- :invalidate=>Cloudinary::Utils.as_safe_bool(options[:invalidate]),
- :eager=>build_eager(options[:eager]),
- :headers=>build_custom_headers(options[:headers]),
- :use_filename=>Cloudinary::Utils.as_safe_bool(options[:use_filename]),
- :unique_filename=>Cloudinary::Utils.as_safe_bool(options[:unique_filename]),
- :overwrite=>Cloudinary::Utils.as_safe_bool(options[:overwrite]),
- :discard_original_filename=>Cloudinary::Utils.as_safe_bool(options[:discard_original_filename]),
- :notification_url=>options[:notification_url],
- :eager_notification_url=>options[:eager_notification_url],
- :eager_async=>Cloudinary::Utils.as_safe_bool(options[:eager_async]),
- :proxy=>options[:proxy],
- :folder=>options[:folder],
+# Copyright Cloudinary
+require 'rest_client'
+require 'json'
+
+class Cloudinary::Uploader
+
+ def self.build_eager(eager)
+ return nil if eager.nil?
+ Cloudinary::Utils.build_array(eager).map do
+ |transformation, format|
+ transformation = transformation.clone
+ format = transformation.delete(:format) || format
+ [Cloudinary::Utils.generate_transformation_string(transformation), format].compact.join("/")
+ end.join("|")
+ end
+
+ def self.build_upload_params(options)
+ params = {:timestamp=>Time.now.to_i,
+ :transformation => Cloudinary::Utils.generate_transformation_string(options.clone),
+ :public_id=> options[:public_id],
+ :callback=> options[:callback],
+ :format=>options[:format],
+ :type=>options[:type],
+ :backup=>Cloudinary::Utils.as_safe_bool(options[:backup]),
+ :faces=>Cloudinary::Utils.as_safe_bool(options[:faces]),
+ :exif=>Cloudinary::Utils.as_safe_bool(options[:exif]),
+ :colors=>Cloudinary::Utils.as_safe_bool(options[:colors]),
+ :image_metadata=>Cloudinary::Utils.as_safe_bool(options[:image_metadata]),
+ :invalidate=>Cloudinary::Utils.as_safe_bool(options[:invalidate]),
+ :eager=>build_eager(options[:eager]),
+ :headers=>build_custom_headers(options[:headers]),
+ :use_filename=>Cloudinary::Utils.as_safe_bool(options[:use_filename]),
+ :unique_filename=>Cloudinary::Utils.as_safe_bool(options[:unique_filename]),
+ :overwrite=>Cloudinary::Utils.as_safe_bool(options[:overwrite]),
+ :discard_original_filename=>Cloudinary::Utils.as_safe_bool(options[:discard_original_filename]),
+ :notification_url=>options[:notification_url],
+ :eager_notification_url=>options[:eager_notification_url],
+ :eager_async=>Cloudinary::Utils.as_safe_bool(options[:eager_async]),
+ :proxy=>options[:proxy],
+ :folder=>options[:folder],
:allowed_formats => Cloudinary::Utils.build_array(options[:allowed_formats]).join(","),
- :tags=>options[:tags] && Cloudinary::Utils.build_array(options[:tags]).join(","),
- :context => Cloudinary::Utils.encode_hash(options[:context]),
- :face_coordinates => Cloudinary::Utils.encode_double_array(options[:face_coordinates]),
- :moderation => options[:moderation],
- :raw_convert => options[:raw_convert],
- :ocr => options[:ocr],
- :categorization => options[:categorization],
+ :tags=>options[:tags] && Cloudinary::Utils.build_array(options[:tags]).join(","),
+ :context => Cloudinary::Utils.encode_hash(options[:context]),
+ :face_coordinates => Cloudinary::Utils.encode_double_array(options[:face_coordinates]),
+ :moderation => options[:moderation],
+ :raw_convert => options[:raw_convert],
+ :ocr => options[:ocr],
+ :categorization => options[:categorization],
:detection => options[:detection],
:similarity_search => options[:similarity_search],
- :auto_tagging => options[:auto_tagging] && options[:auto_tagging].to_f}
- params
- end
-
- def self.upload(file, options={})
- call_api("upload", options) do
- params = build_upload_params(options)
- if file.is_a?(Pathname)
- params[:file] = File.open(file, "rb")
- elsif file.respond_to?(:read) || file =~ /^https?:|^s3:|^data:[^;]*;base64,([a-zA-Z0-9\/+\n=]+)$/
- params[:file] = file
- else
- params[:file] = File.open(file, "rb")
- end
- [params, [:file]]
- end
- end
-
+ :auto_tagging => options[:auto_tagging] && options[:auto_tagging].to_f}
+ params
+ end
+
+ def self.upload(file, options={})
+ call_api("upload", options) do
+ params = build_upload_params(options)
+ if file.is_a?(Pathname)
+ params[:file] = File.open(file, "rb")
+ elsif file.respond_to?(:read) || file =~ /^https?:|^s3:|^data:[^;]*;base64,([a-zA-Z0-9\/+\n=]+)$/
+ params[:file] = file
+ else
+ params[:file] = File.open(file, "rb")
+ end
+ [params, [:file]]
+ end
+ end
+
# Upload large raw files. Note that public_id should include an extension for best results.
- def self.upload_large(file, public_id, options={})
+ def self.upload_large(file, public_id_or_options={}, old_options={})
+ if public_id_or_options.is_a?(Hash)
+ options = public_id_or_options
+ public_id = options[:public_id]
+ else
+ public_id = public_id_or_options
+ options = old_options
+ end
if file.is_a?(Pathname) || !file.respond_to?(:read)
+ filename = file
file = File.open(file, "rb")
+ else
+ filename = "cloudinaryfile"
end
upload = upload_id = nil
index = 1
while !file.eof?
buffer = file.read(20_000_000)
- upload = upload_large_part(Cloudinary::Blob.new(buffer), public_id, options.merge(:upload_id=>upload_id, :part_number=>index, :final=>file.eof?))
- upload_id = upload["upload_id"]
+ upload = upload_large_part(Cloudinary::Blob.new(buffer, :original_filename=>filename), options.merge(:public_id=>public_id, :upload_id=>upload_id, :part_number=>index, :final=>file.eof?))
+ upload_id = upload["upload_id"]
+ public_id = upload["public_id"]
index += 1
end
upload
end
# Upload large raw files. Note that public_id should include an extension for best results.
- def self.upload_large_part(file, public_id, options={})
+ def self.upload_large_part(file, options={})
call_api("upload_large", options.merge(:resource_type=>:raw)) do
params = {
:timestamp=>Time.now.to_i,
:type=>options[:type],
- :public_id=> public_id,
+ :public_id=>options[:public_id],
:backup=>options[:backup],
:final=>options[:final],
:part_number=>options[:part_number],
:upload_id=>options[:upload_id]
}
@@ -101,181 +112,181 @@
params[:file] = file
end
[params, [:file]]
end
end
+
+ def self.destroy(public_id, options={})
+ call_api("destroy", options) do
+ {
+ :timestamp=>Time.now.to_i,
+ :type=>options[:type],
+ :public_id=> public_id,
+ :invalidate=>options[:invalidate],
+ }
+ end
+ end
+
+ def self.rename(from_public_id, to_public_id, options={})
+ call_api("rename", options) do
+ {
+ :timestamp=>Time.now.to_i,
+ :type=>options[:type],
+ :overwrite=>options[:overwrite],
+ :from_public_id=>from_public_id,
+ :to_public_id=>to_public_id,
+ }
+ end
+ end
+
+ def self.exists?(public_id, options={})
+ cloudinary_url = Cloudinary::Utils.cloudinary_url(public_id, options)
+ begin
+ RestClient::Request.execute(:method => :head, :url => cloudinary_url, :timeout=>5).code.to_s =~ /2\d{2}/
+ rescue RestClient::ResourceNotFound => e
+ return false
+ end
+
+ end
+
+ def self.explicit(public_id, options={})
+ call_api("explicit", options) do
+ {
+ :timestamp=>Time.now.to_i,
+ :type=>options[:type],
+ :public_id=> public_id,
+ :callback=> options[:callback],
+ :eager=>build_eager(options[:eager]),
+ :headers=>build_custom_headers(options[:headers]),
+ :tags=>options[:tags] && Cloudinary::Utils.build_array(options[:tags]).join(","),
+ :face_coordinates => options[:face_coordinates] && Cloudinary::Utils.encode_double_array(options[:face_coordinates])
+ }
+ end
+ end
+
+ TEXT_PARAMS = [:public_id, :font_family, :font_size, :font_color, :text_align, :font_weight, :font_style, :background, :opacity, :text_decoration, :line_spacing]
+ def self.text(text, options={})
+ call_api("text", options) do
+ params = {:timestamp => Time.now.to_i, :text=>text}
+ TEXT_PARAMS.each{|k| params[k] = options[k] if !options[k].nil?}
+ params
+ end
+ end
+
+ def self.generate_sprite(tag, options={})
+ version_store = options.delete(:version_store)
+
+ result = call_api("sprite", options) do
+ {
+ :timestamp=>Time.now.to_i,
+ :tag=>tag,
+ :async=>options[:async],
+ :notification_url=>options[:notification_url],
+ :transformation => Cloudinary::Utils.generate_transformation_string(options.merge(:fetch_format=>options[:format]))
+ }
+ end
+
+ if version_store == :file && result && result["version"]
+ if defined?(Rails) && defined?(Rails.root)
+ FileUtils.mkdir_p("#{Rails.root}/tmp/cloudinary")
+ File.open("#{Rails.root}/tmp/cloudinary/cloudinary_sprite_#{tag}.version", "w"){|file| file.print result["version"].to_s}
+ end
+ end
+ return result
+ end
+
+ def self.multi(tag, options={})
+ call_api("multi", options) do
+ {
+ :timestamp=>Time.now.to_i,
+ :tag=>tag,
+ :format=>options[:format],
+ :async=>options[:async],
+ :notification_url=>options[:notification_url],
+ :transformation => Cloudinary::Utils.generate_transformation_string(options.clone)
+ }
+ end
+ end
- def self.destroy(public_id, options={})
- call_api("destroy", options) do
- {
- :timestamp=>Time.now.to_i,
- :type=>options[:type],
- :public_id=> public_id,
- :invalidate=>options[:invalidate],
- }
- end
- end
-
- def self.rename(from_public_id, to_public_id, options={})
- call_api("rename", options) do
- {
- :timestamp=>Time.now.to_i,
- :type=>options[:type],
- :overwrite=>options[:overwrite],
- :from_public_id=>from_public_id,
- :to_public_id=>to_public_id,
- }
- end
- end
-
- def self.exists?(public_id, options={})
- cloudinary_url = Cloudinary::Utils.cloudinary_url(public_id, options)
- begin
- RestClient::Request.execute(:method => :head, :url => cloudinary_url, :timeout=>5).code.to_s =~ /2\d{2}/
- rescue RestClient::ResourceNotFound => e
- return false
- end
-
- end
-
- def self.explicit(public_id, options={})
- call_api("explicit", options) do
- {
- :timestamp=>Time.now.to_i,
- :type=>options[:type],
- :public_id=> public_id,
- :callback=> options[:callback],
- :eager=>build_eager(options[:eager]),
- :headers=>build_custom_headers(options[:headers]),
- :tags=>options[:tags] && Cloudinary::Utils.build_array(options[:tags]).join(","),
- :face_coordinates => options[:face_coordinates] && Cloudinary::Utils.encode_double_array(options[:face_coordinates])
- }
- end
- end
-
- TEXT_PARAMS = [:public_id, :font_family, :font_size, :font_color, :text_align, :font_weight, :font_style, :background, :opacity, :text_decoration, :line_spacing]
- def self.text(text, options={})
- call_api("text", options) do
- params = {:timestamp => Time.now.to_i, :text=>text}
- TEXT_PARAMS.each{|k| params[k] = options[k] if !options[k].nil?}
- params
- end
- end
-
- def self.generate_sprite(tag, options={})
- version_store = options.delete(:version_store)
-
- result = call_api("sprite", options) do
- {
- :timestamp=>Time.now.to_i,
- :tag=>tag,
- :async=>options[:async],
- :notification_url=>options[:notification_url],
- :transformation => Cloudinary::Utils.generate_transformation_string(options.merge(:fetch_format=>options[:format]))
- }
- end
-
- if version_store == :file && result && result["version"]
- if defined?(Rails) && defined?(Rails.root)
- FileUtils.mkdir_p("#{Rails.root}/tmp/cloudinary")
- File.open("#{Rails.root}/tmp/cloudinary/cloudinary_sprite_#{tag}.version", "w"){|file| file.print result["version"].to_s}
- end
- end
- return result
- end
-
- def self.multi(tag, options={})
- call_api("multi", options) do
- {
- :timestamp=>Time.now.to_i,
- :tag=>tag,
- :format=>options[:format],
- :async=>options[:async],
- :notification_url=>options[:notification_url],
- :transformation => Cloudinary::Utils.generate_transformation_string(options.clone)
- }
- end
- end
-
- def self.explode(public_id, options={})
- call_api("explode", options) do
- {
- :timestamp=>Time.now.to_i,
- :public_id=>public_id,
- :type=>options[:type],
- :format=>options[:format],
- :notification_url=>options[:notification_url],
- :transformation => Cloudinary::Utils.generate_transformation_string(options.clone)
- }
- end
- end
-
- # options may include 'exclusive' (boolean) which causes clearing this tag from all other resources
- def self.add_tag(tag, public_ids = [], options = {})
- exclusive = options.delete(:exclusive)
- command = exclusive ? "set_exclusive" : "add"
- return self.call_tags_api(tag, command, public_ids, options)
- end
-
- def self.remove_tag(tag, public_ids = [], options = {})
- return self.call_tags_api(tag, "remove", public_ids, options)
- end
-
- def self.replace_tag(tag, public_ids = [], options = {})
- return self.call_tags_api(tag, "replace", public_ids, options)
- end
-
- private
-
- def self.call_tags_api(tag, command, public_ids = [], options = {})
- return call_api("tags", options) do
- {
- :timestamp=>Time.now.to_i,
- :tag=>tag,
- :public_ids => Cloudinary::Utils.build_array(public_ids),
- :command => command,
- :type => options[:type]
- }
- end
- end
-
- def self.call_api(action, options)
- options = options.clone
- return_error = options.delete(:return_error)
- api_key = options[:api_key] || Cloudinary.config.api_key || raise(CloudinaryException, "Must supply api_key")
- api_secret = options[:api_secret] || Cloudinary.config.api_secret || raise(CloudinaryException, "Must supply api_secret")
-
- params, non_signable = yield
- non_signable ||= []
-
- params[:signature] = Cloudinary::Utils.api_sign_request(params.reject{|k,v| non_signable.include?(k)}, api_secret)
- params[:api_key] = api_key
-
- result = nil
-
- api_url = Cloudinary::Utils.cloudinary_api_url(action, options)
-
- RestClient::Request.execute(:method => :post, :url => api_url, :payload => params.reject{|k, v| v.nil? || v==""}, :timeout=>60, :headers => {"User-Agent" => Cloudinary::USER_AGENT}) do
- |response, request, tmpresult|
- raise CloudinaryException, "Server returned unexpected status code - #{response.code} - #{response.body}" if ![200,400,401,403,404,500].include?(response.code)
- begin
- result = Cloudinary::Utils.json_decode(response.body)
- rescue => e
- # Error is parsing json
- raise CloudinaryException, "Error parsing server response (#{response.code}) - #{response.body}. Got - #{e}"
- end
- if result["error"]
- if return_error
- result["error"]["http_code"] = response.code
- else
- raise CloudinaryException, result["error"]["message"]
- end
- end
- end
-
- result
- end
-
- def self.build_custom_headers(headers)
- Array(headers).map{|*a| a.join(": ")}.join("\n")
- end
-end
+ def self.explode(public_id, options={})
+ call_api("explode", options) do
+ {
+ :timestamp=>Time.now.to_i,
+ :public_id=>public_id,
+ :type=>options[:type],
+ :format=>options[:format],
+ :notification_url=>options[:notification_url],
+ :transformation => Cloudinary::Utils.generate_transformation_string(options.clone)
+ }
+ end
+ end
+
+ # options may include 'exclusive' (boolean) which causes clearing this tag from all other resources
+ def self.add_tag(tag, public_ids = [], options = {})
+ exclusive = options.delete(:exclusive)
+ command = exclusive ? "set_exclusive" : "add"
+ return self.call_tags_api(tag, command, public_ids, options)
+ end
+
+ def self.remove_tag(tag, public_ids = [], options = {})
+ return self.call_tags_api(tag, "remove", public_ids, options)
+ end
+
+ def self.replace_tag(tag, public_ids = [], options = {})
+ return self.call_tags_api(tag, "replace", public_ids, options)
+ end
+
+ private
+
+ def self.call_tags_api(tag, command, public_ids = [], options = {})
+ return call_api("tags", options) do
+ {
+ :timestamp=>Time.now.to_i,
+ :tag=>tag,
+ :public_ids => Cloudinary::Utils.build_array(public_ids),
+ :command => command,
+ :type => options[:type]
+ }
+ end
+ end
+
+ def self.call_api(action, options)
+ options = options.clone
+ return_error = options.delete(:return_error)
+ api_key = options[:api_key] || Cloudinary.config.api_key || raise(CloudinaryException, "Must supply api_key")
+ api_secret = options[:api_secret] || Cloudinary.config.api_secret || raise(CloudinaryException, "Must supply api_secret")
+
+ params, non_signable = yield
+ non_signable ||= []
+
+ params[:signature] = Cloudinary::Utils.api_sign_request(params.reject{|k,v| non_signable.include?(k)}, api_secret)
+ params[:api_key] = api_key
+
+ result = nil
+
+ api_url = Cloudinary::Utils.cloudinary_api_url(action, options)
+
+ RestClient::Request.execute(:method => :post, :url => api_url, :payload => params.reject{|k, v| v.nil? || v==""}, :timeout=>60, :headers => {"User-Agent" => Cloudinary::USER_AGENT}) do
+ |response, request, tmpresult|
+ raise CloudinaryException, "Server returned unexpected status code - #{response.code} - #{response.body}" if ![200,400,401,403,404,500].include?(response.code)
+ begin
+ result = Cloudinary::Utils.json_decode(response.body)
+ rescue => e
+ # Error is parsing json
+ raise CloudinaryException, "Error parsing server response (#{response.code}) - #{response.body}. Got - #{e}"
+ end
+ if result["error"]
+ if return_error
+ result["error"]["http_code"] = response.code
+ else
+ raise CloudinaryException, result["error"]["message"]
+ end
+ end
+ end
+
+ result
+ end
+
+ def self.build_custom_headers(headers)
+ Array(headers).map{|*a| a.join(": ")}.join("\n")
+ end
+end