lib/carrierwave/storage/upyun.rb in carrierwave-upyun-1.0.0 vs lib/carrierwave/storage/upyun.rb in carrierwave-upyun-1.0.1

- old
+ new

@@ -1,6 +1,7 @@ -# coding: utf-8 +# frozen_string_literal: true + require "faraday" module CarrierWave module Storage ## @@ -13,12 +14,15 @@ # config.upyun_api_host = "http://v0.api.upyun.com" # end # # class UpYun < Abstract - DEFAULT_API_URL = 'http://v0.api.upyun.com' + DEFAULT_API_URL = "http://v0.api.upyun.com" + class UploadError < RuntimeError; end + class ConcurrentUploadError < RuntimeError; end + class File < CarrierWave::SanitizedFile def initialize(uploader, base, path) @uploader = uploader @path = path @base = base @@ -29,25 +33,21 @@ # # === Returns # # [String] A path # - def path - @path - end + attr_reader :path def escaped_path @escaped_path ||= CGI.escape(@path) end def content_type @content_type || "" end - def content_type=(new_content_type) - @content_type = new_content_type - end + attr_writer :content_type ## # Reads the contents of the file from Cloud Files # # === Returns @@ -62,17 +62,15 @@ ## # Remove the file from Cloud Files # def delete - begin - conn.delete(escaped_path) - true - rescue => e - puts "carrierwave-upyun delete failed: #{e.inspect}" - nil - end + conn.delete(escaped_path) + true + rescue StandardError => e + puts "carrierwave-upyun delete failed: #{e.inspect}" + nil end ## # Returns the url on the Cloud Files CDN. Note that the parent container must be marked as # public for this to work. @@ -81,10 +79,11 @@ # # [String] file's url # def url return nil unless @uploader.upyun_bucket_host + [@uploader.upyun_bucket_host, @path].join("/") end def content_type headers[:content_type] @@ -99,38 +98,46 @@ # # === Returns # # boolean # - def store(data, headers = {}) - res = conn.put(escaped_path, data) do |req| - req.headers = {'Expect' => '', 'Mkdir' => 'true'}.merge(headers) + def store(new_file, headers = {}) + res = conn.put(escaped_path, new_file.read) do |req| + req.headers = { "Expect" => "", "Mkdir" => "true" }.merge(headers) end + if res.status != 200 - puts "Update failed: #{res.body}" - return false + # code: 42900007 -> concurrent put or delete + json = JSON.parse(res.body) + # retry upload + raise ConcurrentUploadError, res.body if json["code"] == 42_900_007 + + raise UploadError, res.body end true + rescue ConcurrentUploadError => e + puts "Warning: UpYun error #{e.message}, retry again." + retry end def headers @headers ||= begin conn.get(@path).headers - rescue Faraday::ClientError - {} + rescue Faraday::ClientError + {} end end def conn - return @conn if defined?(@conn) - - api_host = @uploader.upyun_api_host || DEFAULT_API_URL - @conn = Faraday.new(url: "#{api_host}/#{@uploader.upyun_bucket}") do |req| - req.request :basic_auth, @uploader.upyun_username, @uploader.upyun_password - req.request :url_encoded - req.adapter Faraday.default_adapter + @conn ||= begin + api_host = @uploader.upyun_api_host || DEFAULT_API_URL + Faraday.new(url: "#{api_host}/#{@uploader.upyun_bucket}") do |req| + req.request :basic_auth, @uploader.upyun_username, @uploader.upyun_password + req.request :url_encoded + req.adapter Faraday.default_adapter + end end end end # File ## @@ -144,11 +151,11 @@ # # [CarrierWave::Storage::UpYun::File] the stored file # def store!(file) f = File.new(uploader, self, uploader.store_path) - f.store(file.read, 'Content-Type' => file.content_type) + f.store(file, "Content-Type" => file.content_type) f end # Do something to retrieve the file # @@ -163,22 +170,20 @@ def retrieve!(identifier) File.new(uploader, self, uploader.store_path(identifier)) end def cache!(file) - f = File.new(uploader, self, uploader.store_path) - f.store(file.read, 'Content-Type' => file.content_type) + f = File.new(uploader, self, uploader.cache_path) + f.store(file, "Content-Type" => file.content_type) f end def retrieve_from_cache!(identifier) File.new(uploader, self, uploader.cache_path(identifier)) end - def delete_dir!(path) - end + def delete_dir!(path); end - def clean_cache!(seconds) - end + def clean_cache!(seconds); end end # CloudFiles end # Storage end # CarrierWave