cloudfuji_paperclip 2.4.6 → 3.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/.travis.yml +9 -6
- data/Appraisals +6 -6
- data/CONTRIBUTING.md +34 -2
- data/Gemfile +2 -0
- data/NEWS +90 -0
- data/README.md +62 -29
- data/RUNNING_TESTS.md +4 -0
- data/Rakefile +7 -2
- data/UPGRADING +14 -0
- data/features/basic_integration.feature +11 -7
- data/features/rake_tasks.feature +1 -1
- data/features/step_definitions/attachment_steps.rb +11 -2
- data/features/step_definitions/rails_steps.rb +17 -79
- data/features/support/env.rb +3 -0
- data/features/support/fakeweb.rb +7 -0
- data/features/support/file_helpers.rb +24 -0
- data/features/support/rails.rb +3 -3
- data/gemfiles/{rails3_1.gemfile → 3.0.gemfile} +3 -1
- data/gemfiles/{rails2.gemfile → 3.1.gemfile} +3 -1
- data/gemfiles/{rails3.gemfile → 3.2.gemfile} +3 -1
- data/images.rake +21 -0
- data/lib/cloudfuji_paperclip.rb +1 -0
- data/lib/generators/paperclip/paperclip_generator.rb +1 -2
- data/lib/paperclip.rb +54 -319
- data/lib/paperclip/attachment.rb +86 -107
- data/lib/paperclip/attachment_options.rb +9 -0
- data/lib/paperclip/callbacks.rb +30 -0
- data/lib/paperclip/errors.rb +27 -0
- data/lib/paperclip/geometry.rb +6 -4
- data/lib/paperclip/glue.rb +23 -0
- data/lib/paperclip/helpers.rb +71 -0
- data/lib/paperclip/instance_methods.rb +35 -0
- data/lib/paperclip/interpolations.rb +4 -4
- data/lib/paperclip/io_adapters/attachment_adapter.rb +69 -0
- data/lib/paperclip/io_adapters/file_adapter.rb +81 -0
- data/lib/paperclip/io_adapters/identity_adapter.rb +12 -0
- data/lib/paperclip/io_adapters/nil_adapter.rb +34 -0
- data/lib/paperclip/io_adapters/registry.rb +32 -0
- data/lib/paperclip/io_adapters/stringio_adapter.rb +64 -0
- data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +63 -0
- data/lib/paperclip/locales/en.yml +17 -0
- data/lib/paperclip/logger.rb +21 -0
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +5 -5
- data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +7 -7
- data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +11 -11
- data/lib/paperclip/missing_attachment_styles.rb +6 -9
- data/lib/paperclip/processor.rb +32 -17
- data/lib/paperclip/railtie.rb +13 -17
- data/lib/paperclip/storage/filesystem.rb +4 -13
- data/lib/paperclip/storage/fog.rb +33 -24
- data/lib/paperclip/storage/s3.rb +36 -28
- data/lib/paperclip/tempfile.rb +41 -0
- data/lib/paperclip/thumbnail.rb +2 -3
- data/lib/paperclip/validators.rb +45 -0
- data/lib/paperclip/validators/attachment_content_type_validator.rb +54 -0
- data/lib/paperclip/validators/attachment_presence_validator.rb +26 -0
- data/lib/paperclip/validators/attachment_size_validator.rb +102 -0
- data/lib/paperclip/version.rb +1 -1
- data/lib/tasks/paperclip.rake +4 -12
- data/paperclip.gemspec +15 -5
- data/test/adapter_registry_test.rb +32 -0
- data/test/attachment_adapter_test.rb +51 -0
- data/test/attachment_options_test.rb +27 -0
- data/test/attachment_test.rb +130 -46
- data/test/file_adapter_test.rb +88 -0
- data/test/generator_test.rb +78 -0
- data/test/geometry_test.rb +5 -5
- data/test/helper.rb +21 -22
- data/test/identity_adapter_test.rb +8 -0
- data/test/integration_test.rb +55 -102
- data/test/interpolations_test.rb +15 -5
- data/test/matchers/validate_attachment_content_type_matcher_test.rb +23 -0
- data/test/matchers/validate_attachment_presence_matcher_test.rb +21 -0
- data/test/matchers/validate_attachment_size_matcher_test.rb +37 -2
- data/test/nil_adapter_test.rb +25 -0
- data/test/paperclip_missing_attachment_styles_test.rb +16 -0
- data/test/paperclip_test.rb +34 -183
- data/test/storage/filesystem_test.rb +27 -27
- data/test/storage/fog_test.rb +68 -12
- data/test/storage/s3_live_test.rb +79 -38
- data/test/storage/s3_test.rb +204 -34
- data/test/stringio_adapter_test.rb +42 -0
- data/test/thumbnail_test.rb +29 -8
- data/test/uploaded_file_adapter_test.rb +98 -0
- data/test/url_generator_test.rb +8 -8
- data/test/validators/attachment_content_type_validator_test.rb +192 -0
- data/test/validators/attachment_presence_validator_test.rb +85 -0
- data/test/validators/attachment_size_validator_test.rb +207 -0
- data/test/validators_test.rb +25 -0
- metadata +166 -59
- data/generators/paperclip/USAGE +0 -5
- data/generators/paperclip/paperclip_generator.rb +0 -27
- data/generators/paperclip/templates/paperclip_migration.rb.erb +0 -19
- data/init.rb +0 -4
- data/lib/paperclip/callback_compatibility.rb +0 -61
- data/lib/paperclip/iostream.rb +0 -45
- data/lib/paperclip/upfile.rb +0 -62
- data/rails/init.rb +0 -2
- data/test/.gitignore +0 -1
- data/test/fixtures/question?mark.png +0 -0
- data/test/iostream_test.rb +0 -71
- data/test/upfile_test.rb +0 -53
@@ -0,0 +1,21 @@
|
|
1
|
+
module Paperclip
|
2
|
+
module Logger
|
3
|
+
# Log a paperclip-specific line. This will log to STDOUT
|
4
|
+
# by default. Set Paperclip.options[:log] to false to turn off.
|
5
|
+
def log message
|
6
|
+
logger.info("[paperclip] #{message}") if logging?
|
7
|
+
end
|
8
|
+
|
9
|
+
def logger #:nodoc:
|
10
|
+
@logger ||= options[:logger] || ::Logger.new(STDOUT)
|
11
|
+
end
|
12
|
+
|
13
|
+
def logger=(logger)
|
14
|
+
@logger = logger
|
15
|
+
end
|
16
|
+
|
17
|
+
def logging? #:nodoc:
|
18
|
+
options[:log]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -33,7 +33,7 @@ module Paperclip
|
|
33
33
|
|
34
34
|
def matches? subject
|
35
35
|
@subject = subject
|
36
|
-
@subject = @subject.class
|
36
|
+
@subject = @subject.new if @subject.class == Class
|
37
37
|
@allowed_types && @rejected_types &&
|
38
38
|
allowed_types_allowed? && rejected_types_rejected?
|
39
39
|
end
|
@@ -61,11 +61,11 @@ module Paperclip
|
|
61
61
|
protected
|
62
62
|
|
63
63
|
def type_allowed?(type)
|
64
|
-
file = StringIO.new(".")
|
64
|
+
file = Paperclip.io_adapters.for(StringIO.new("."))
|
65
65
|
file.content_type = type
|
66
|
-
|
67
|
-
subject.valid?
|
68
|
-
subject.errors[:"#{@attachment_name}_content_type"].blank?
|
66
|
+
@subject.attachment_for(@attachment_name).assign(file)
|
67
|
+
@subject.valid?
|
68
|
+
@subject.errors[:"#{@attachment_name}_content_type"].blank?
|
69
69
|
end
|
70
70
|
|
71
71
|
def allowed_types_allowed?
|
@@ -18,7 +18,7 @@ module Paperclip
|
|
18
18
|
|
19
19
|
def matches? subject
|
20
20
|
@subject = subject
|
21
|
-
@subject =
|
21
|
+
@subject = subject.new if subject.class == Class
|
22
22
|
error_when_not_valid? && no_error_when_valid?
|
23
23
|
end
|
24
24
|
|
@@ -37,16 +37,16 @@ module Paperclip
|
|
37
37
|
protected
|
38
38
|
|
39
39
|
def error_when_not_valid?
|
40
|
-
|
41
|
-
subject.valid?
|
42
|
-
|
40
|
+
@subject.send(@attachment_name).assign(nil)
|
41
|
+
@subject.valid?
|
42
|
+
@subject.errors[:"#{@attachment_name}"].present?
|
43
43
|
end
|
44
44
|
|
45
45
|
def no_error_when_valid?
|
46
46
|
@file = StringIO.new(".")
|
47
|
-
|
48
|
-
subject.valid?
|
49
|
-
subject.errors[:"#{@attachment_name}
|
47
|
+
@subject.send(@attachment_name).assign(@file)
|
48
|
+
@subject.valid?
|
49
|
+
@subject.errors[:"#{@attachment_name}"].blank?
|
50
50
|
end
|
51
51
|
end
|
52
52
|
end
|
@@ -18,7 +18,6 @@ module Paperclip
|
|
18
18
|
class ValidateAttachmentSizeMatcher
|
19
19
|
def initialize attachment_name
|
20
20
|
@attachment_name = attachment_name
|
21
|
-
@low, @high = 0, (1.0/0)
|
22
21
|
end
|
23
22
|
|
24
23
|
def less_than size
|
@@ -38,7 +37,7 @@ module Paperclip
|
|
38
37
|
|
39
38
|
def matches? subject
|
40
39
|
@subject = subject
|
41
|
-
@subject = @subject.class
|
40
|
+
@subject = @subject.new if @subject.class == Class
|
42
41
|
lower_than_low? && higher_than_low? && lower_than_high? && higher_than_high?
|
43
42
|
end
|
44
43
|
|
@@ -67,27 +66,28 @@ module Paperclip
|
|
67
66
|
override_method(file, :size){ new_size }
|
68
67
|
override_method(file, :to_tempfile){ file }
|
69
68
|
|
70
|
-
|
71
|
-
subject.
|
72
|
-
subject.
|
69
|
+
@subject.send(@attachment_name).post_processing = false
|
70
|
+
@subject.send(@attachment_name).assign(file)
|
71
|
+
@subject.valid?
|
72
|
+
@subject.errors[:"#{@attachment_name}_file_size"].blank?
|
73
|
+
ensure
|
74
|
+
@subject.send(@attachment_name).post_processing = true
|
73
75
|
end
|
74
76
|
|
75
77
|
def lower_than_low?
|
76
|
-
|
78
|
+
@low.nil? || !passes_validation_with_size(@low - 1)
|
77
79
|
end
|
78
80
|
|
79
81
|
def higher_than_low?
|
80
|
-
passes_validation_with_size(@low + 1)
|
82
|
+
@low.nil? || passes_validation_with_size(@low + 1)
|
81
83
|
end
|
82
84
|
|
83
85
|
def lower_than_high?
|
84
|
-
|
85
|
-
passes_validation_with_size(@high - 1)
|
86
|
+
@high.nil? || @high == Float::INFINITY || passes_validation_with_size(@high - 1)
|
86
87
|
end
|
87
88
|
|
88
89
|
def higher_than_high?
|
89
|
-
|
90
|
-
not passes_validation_with_size(@high + 1)
|
90
|
+
@high.nil? || @high == Float::INFINITY || !passes_validation_with_size(@high + 1)
|
91
91
|
end
|
92
92
|
end
|
93
93
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
|
2
2
|
require 'set'
|
3
3
|
module Paperclip
|
4
|
-
|
5
4
|
class << self
|
6
5
|
attr_accessor :classes_with_attachments
|
7
6
|
attr_writer :registered_attachments_styles_path
|
@@ -12,7 +11,6 @@ module Paperclip
|
|
12
11
|
|
13
12
|
self.classes_with_attachments = Set.new
|
14
13
|
|
15
|
-
|
16
14
|
# Get list of styles saved on previous deploy (running rake paperclip:refresh:missing_styles)
|
17
15
|
def self.get_registered_attachments_styles
|
18
16
|
YAML.load_file(Paperclip.registered_attachments_styles_path)
|
@@ -49,9 +47,9 @@ module Paperclip
|
|
49
47
|
current_styles[klass_sym][attachment_name.to_sym] ||= Array.new
|
50
48
|
current_styles[klass_sym][attachment_name.to_sym] << style_name.to_sym
|
51
49
|
current_styles[klass_sym][attachment_name.to_sym].map!(&:to_s).sort!.map!(&:to_sym).uniq!
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
55
53
|
end
|
56
54
|
end
|
57
55
|
private_class_method :current_attachments_styles
|
@@ -70,8 +68,8 @@ module Paperclip
|
|
70
68
|
Hash.new.tap do |missing_styles|
|
71
69
|
current_styles.each do |klass, attachment_definitions|
|
72
70
|
attachment_definitions.each do |attachment_name, styles|
|
73
|
-
registered = registered_styles[klass][attachment_name] rescue []
|
74
|
-
missed = styles - registered
|
71
|
+
registered = registered_styles[klass][attachment_name] || [] rescue []
|
72
|
+
missed = styles - registered
|
75
73
|
if missed.present?
|
76
74
|
klass_sym = klass.to_s.to_sym
|
77
75
|
missing_styles[klass_sym] ||= Hash.new
|
@@ -80,8 +78,7 @@ module Paperclip
|
|
80
78
|
missing_styles[klass_sym][attachment_name.to_sym].map!(&:to_s).sort!.map!(&:to_sym).uniq!
|
81
79
|
end
|
82
80
|
end
|
83
|
-
end
|
81
|
+
end
|
84
82
|
end
|
85
83
|
end
|
86
|
-
|
87
84
|
end
|
data/lib/paperclip/processor.rb
CHANGED
@@ -34,25 +34,40 @@ module Paperclip
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
else
|
50
|
-
prefix, suffix = basename, ''
|
51
|
-
end
|
37
|
+
module ProcessorHelpers
|
38
|
+
def processor(name) #:nodoc:
|
39
|
+
@known_processors ||= {}
|
40
|
+
if @known_processors[name.to_s]
|
41
|
+
@known_processors[name.to_s]
|
42
|
+
else
|
43
|
+
name = name.to_s.camelize
|
44
|
+
load_processor(name) unless Paperclip.const_defined?(name)
|
45
|
+
processor = Paperclip.const_get(name)
|
46
|
+
@known_processors[name.to_s] = processor
|
47
|
+
end
|
48
|
+
end
|
52
49
|
|
53
|
-
|
54
|
-
|
50
|
+
def load_processor(name)
|
51
|
+
if defined?(Rails.root) && Rails.root
|
52
|
+
require File.expand_path(Rails.root.join("lib", "paperclip_processors", "#{name.underscore}.rb"))
|
55
53
|
end
|
56
54
|
end
|
55
|
+
|
56
|
+
def clear_processors!
|
57
|
+
@known_processors.try(:clear)
|
58
|
+
end
|
59
|
+
|
60
|
+
# You can add your own processor via the Paperclip configuration. Normally
|
61
|
+
# Paperclip will load all processors from the
|
62
|
+
# Rails.root/lib/paperclip_processors directory, but here you can add any
|
63
|
+
# existing class using this mechanism.
|
64
|
+
#
|
65
|
+
# Paperclip.configure do |c|
|
66
|
+
# c.register_processor :watermarker, WatermarkingProcessor.new
|
67
|
+
# end
|
68
|
+
def register_processor(name, processor)
|
69
|
+
@known_processors ||= {}
|
70
|
+
@known_processors[name.to_s] = processor
|
71
|
+
end
|
57
72
|
end
|
58
73
|
end
|
data/lib/paperclip/railtie.rb
CHANGED
@@ -2,30 +2,26 @@ require 'paperclip'
|
|
2
2
|
require 'paperclip/schema'
|
3
3
|
|
4
4
|
module Paperclip
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
12
|
-
end
|
13
|
-
rake_tasks do
|
14
|
-
load "tasks/paperclip.rake"
|
5
|
+
require 'rails'
|
6
|
+
|
7
|
+
class Railtie < Rails::Railtie
|
8
|
+
initializer 'paperclip.insert_into_active_record' do
|
9
|
+
ActiveSupport.on_load :active_record do
|
10
|
+
Paperclip::Railtie.insert
|
15
11
|
end
|
16
12
|
end
|
13
|
+
|
14
|
+
rake_tasks { load "tasks/paperclip.rake" }
|
17
15
|
end
|
18
16
|
|
19
17
|
class Railtie
|
20
18
|
def self.insert
|
21
|
-
|
22
|
-
File.send(:include, Paperclip::Upfile)
|
19
|
+
Paperclip.options[:logger] = Rails.logger
|
23
20
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
ActiveRecord::ConnectionAdapters::TableDefinition.send(:include, Paperclip::Schema)
|
21
|
+
if defined?(ActiveRecord)
|
22
|
+
Paperclip.options[:logger] = ActiveRecord::Base.logger
|
23
|
+
ActiveRecord::Base.send(:include, Paperclip::Glue)
|
24
|
+
end
|
29
25
|
end
|
30
26
|
end
|
31
27
|
end
|
@@ -27,22 +27,13 @@ module Paperclip
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
# Returns representation of the data of the file assigned to the given
|
31
|
-
# style, in the format most representative of the current storage.
|
32
|
-
def to_file style_name = default_style
|
33
|
-
@queued_for_write[style_name] || (File.new(path(style_name), 'rb') if exists?(style_name))
|
34
|
-
end
|
35
|
-
|
36
30
|
def flush_writes #:nodoc:
|
37
31
|
@queued_for_write.each do |style_name, file|
|
38
|
-
file.close
|
39
32
|
FileUtils.mkdir_p(File.dirname(path(style_name)))
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
FileUtils.cp(file.path, path(style_name))
|
45
|
-
FileUtils.rm(file.path)
|
33
|
+
File.open(path(style_name), "wb") do |new_file|
|
34
|
+
while chunk = file.read(16 * 1024)
|
35
|
+
new_file.write(chunk)
|
36
|
+
end
|
46
37
|
end
|
47
38
|
FileUtils.chmod(0666&~File.umask, path(style_name))
|
48
39
|
end
|
@@ -80,9 +80,10 @@ module Paperclip
|
|
80
80
|
retried = false
|
81
81
|
begin
|
82
82
|
directory.files.create(fog_file.merge(
|
83
|
-
:body
|
84
|
-
:key
|
85
|
-
:public
|
83
|
+
:body => file,
|
84
|
+
:key => path(style),
|
85
|
+
:public => fog_public,
|
86
|
+
:content_type => file.content_type
|
86
87
|
))
|
87
88
|
rescue Excon::Errors::NotFound
|
88
89
|
raise if retried
|
@@ -105,27 +106,14 @@ module Paperclip
|
|
105
106
|
@queued_for_delete = []
|
106
107
|
end
|
107
108
|
|
108
|
-
# Returns representation of the data of the file assigned to the given
|
109
|
-
# style, in the format most representative of the current storage.
|
110
|
-
def to_file(style = default_style)
|
111
|
-
if @queued_for_write[style]
|
112
|
-
@queued_for_write[style]
|
113
|
-
else
|
114
|
-
body = directory.files.get(path(style)).body
|
115
|
-
filename = path(style)
|
116
|
-
extname = File.extname(filename)
|
117
|
-
basename = File.basename(filename, extname)
|
118
|
-
file = Tempfile.new([basename, extname])
|
119
|
-
file.binmode
|
120
|
-
file.write(body)
|
121
|
-
file.rewind
|
122
|
-
file
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
109
|
def public_url(style = default_style)
|
127
110
|
if @options[:fog_host]
|
128
|
-
host =
|
111
|
+
host = if @options[:fog_host].respond_to?(:call)
|
112
|
+
@options[:fog_host].call(self)
|
113
|
+
else
|
114
|
+
(@options[:fog_host] =~ /%d/) ? @options[:fog_host] % (path(style).hash % 4) : @options[:fog_host]
|
115
|
+
end
|
116
|
+
|
129
117
|
"#{host}/#{path(style)}"
|
130
118
|
else
|
131
119
|
if fog_credentials[:provider] == 'AWS'
|
@@ -147,6 +135,17 @@ module Paperclip
|
|
147
135
|
(creds[env] || creds).symbolize_keys
|
148
136
|
end
|
149
137
|
|
138
|
+
def copy_to_local_file(style, local_dest_path)
|
139
|
+
log("copying #{path(style)} to local file #{local_dest_path}")
|
140
|
+
local_file = ::File.open(local_dest_path, 'wb')
|
141
|
+
file = directory.files.get(path(style))
|
142
|
+
local_file.write(file.body)
|
143
|
+
local_file.close
|
144
|
+
rescue Fog::Errors::Error => e
|
145
|
+
warn("#{e} - cannot copy #{path(style)} to local file #{local_dest_path}")
|
146
|
+
false
|
147
|
+
end
|
148
|
+
|
150
149
|
private
|
151
150
|
|
152
151
|
def find_credentials(creds)
|
@@ -158,7 +157,11 @@ module Paperclip
|
|
158
157
|
when Hash
|
159
158
|
creds
|
160
159
|
else
|
161
|
-
|
160
|
+
if creds.respond_to?(:call)
|
161
|
+
creds.call(self)
|
162
|
+
else
|
163
|
+
raise ArgumentError, "Credentials are not a path, file, hash or proc."
|
164
|
+
end
|
162
165
|
end
|
163
166
|
end
|
164
167
|
|
@@ -167,7 +170,13 @@ module Paperclip
|
|
167
170
|
end
|
168
171
|
|
169
172
|
def directory
|
170
|
-
|
173
|
+
dir = if @options[:fog_directory].respond_to?(:call)
|
174
|
+
@options[:fog_directory].call(self)
|
175
|
+
else
|
176
|
+
@options[:fog_directory]
|
177
|
+
end
|
178
|
+
|
179
|
+
@directory ||= connection.directories.new(:key => dir)
|
171
180
|
end
|
172
181
|
end
|
173
182
|
end
|
data/lib/paperclip/storage/s3.rb
CHANGED
@@ -41,7 +41,9 @@ module Paperclip
|
|
41
41
|
# * +s3_protocol+: The protocol for the URLs generated to your S3 assets. Can be either
|
42
42
|
# 'http' or 'https'. Defaults to 'http' when your :s3_permissions are :public_read (the
|
43
43
|
# default), and 'https' when your :s3_permissions are anything else.
|
44
|
-
# * +s3_headers+: A hash of headers
|
44
|
+
# * +s3_headers+: A hash of headers or a Proc. You may specify a hash such as
|
45
|
+
# {'Expires' => 1.year.from_now.httpdate}. If you use a Proc, headers are determined at
|
46
|
+
# runtime. Paperclip will call that Proc with attachment as the only argument.
|
45
47
|
# * +bucket+: This is the name of the S3 bucket that will store your files. Remember
|
46
48
|
# that the bucket must be unique across all of Amazon S3. If the bucket does not exist
|
47
49
|
# Paperclip will attempt to create it. The bucket name will not be interpolated.
|
@@ -93,12 +95,14 @@ module Paperclip
|
|
93
95
|
@s3_permissions = set_permissions(@options[:s3_permissions])
|
94
96
|
@s3_protocol = @options[:s3_protocol] ||
|
95
97
|
Proc.new do |style, attachment|
|
96
|
-
permission = (@s3_permissions[style.to_sym] || @s3_permissions[:default])
|
98
|
+
permission = (@s3_permissions[style.to_s.to_sym] || @s3_permissions[:default])
|
97
99
|
permission = permission.call(attachment, style) if permission.is_a?(Proc)
|
98
100
|
(permission == :public_read) ? 'http' : 'https'
|
99
101
|
end
|
100
102
|
@s3_metadata = @options[:s3_metadata] || {}
|
101
|
-
@s3_headers =
|
103
|
+
@s3_headers = @options[:s3_headers] || {}
|
104
|
+
@s3_headers = @s3_headers.call(instance) if @s3_headers.is_a?(Proc)
|
105
|
+
@s3_headers = (@s3_headers).inject({}) do |headers,(name,value)|
|
102
106
|
case name.to_s
|
103
107
|
when /^x-amz-meta-(.*)/i
|
104
108
|
@s3_metadata[$1.downcase] = value
|
@@ -111,6 +115,8 @@ module Paperclip
|
|
111
115
|
|
112
116
|
@s3_headers[:storage_class] = @options[:s3_storage_class] if @options[:s3_storage_class]
|
113
117
|
|
118
|
+
@s3_server_side_encryption = @options[:s3_server_side_encryption]
|
119
|
+
|
114
120
|
unless @options[:url].to_s.match(/^:s3.*url$/) || @options[:url] == ":asset_host"
|
115
121
|
@options[:path] = @options[:path].gsub(/:url/, @options[:url]).gsub(/^:rails_root\/public\/system/, '')
|
116
122
|
@options[:url] = ":s3_path_url"
|
@@ -135,7 +141,8 @@ module Paperclip
|
|
135
141
|
|
136
142
|
def expiring_url(time = 3600, style_name = default_style)
|
137
143
|
if path
|
138
|
-
|
144
|
+
base_options = { :expires => time, :secure => use_secure_protocol?(style_name) }
|
145
|
+
s3_object(style_name).url_for(:read, base_options.merge(s3_url_options)).to_s
|
139
146
|
end
|
140
147
|
end
|
141
148
|
|
@@ -153,6 +160,12 @@ module Paperclip
|
|
153
160
|
@s3_host_alias
|
154
161
|
end
|
155
162
|
|
163
|
+
def s3_url_options
|
164
|
+
s3_url_options = @options[:s3_url_options] || {}
|
165
|
+
s3_url_options = s3_url_options.call(instance) if s3_url_options.is_a?(Proc)
|
166
|
+
s3_url_options
|
167
|
+
end
|
168
|
+
|
156
169
|
def bucket_name
|
157
170
|
@bucket = @options[:bucket] || s3_credentials[:bucket]
|
158
171
|
@bucket = @bucket.call(self) if @bucket.is_a?(Proc)
|
@@ -221,6 +234,7 @@ module Paperclip
|
|
221
234
|
end
|
222
235
|
|
223
236
|
def parse_credentials creds
|
237
|
+
creds = creds.respond_to?('call') ? creds.call(self) : creds
|
224
238
|
creds = find_credentials(creds).stringify_keys
|
225
239
|
env = Object.const_defined?(:Rails) ? Rails.env : nil
|
226
240
|
(creds[env] || creds).symbolize_keys
|
@@ -232,6 +246,8 @@ module Paperclip
|
|
232
246
|
else
|
233
247
|
false
|
234
248
|
end
|
249
|
+
rescue AWS::Errors::Base => e
|
250
|
+
false
|
235
251
|
end
|
236
252
|
|
237
253
|
def s3_permissions(style = default_style)
|
@@ -248,20 +264,6 @@ module Paperclip
|
|
248
264
|
end
|
249
265
|
end
|
250
266
|
|
251
|
-
# Returns representation of the data of the file assigned to the given
|
252
|
-
# style, in the format most representative of the current storage.
|
253
|
-
def to_file style = default_style
|
254
|
-
return @queued_for_write[style] if @queued_for_write[style]
|
255
|
-
filename = path(style)
|
256
|
-
extname = File.extname(filename)
|
257
|
-
basename = File.basename(filename, extname)
|
258
|
-
file = Tempfile.new([basename, extname])
|
259
|
-
file.binmode
|
260
|
-
file.write(s3_object(style).read)
|
261
|
-
file.rewind
|
262
|
-
return file
|
263
|
-
end
|
264
|
-
|
265
267
|
def create_bucket
|
266
268
|
s3_interface.buckets.create(bucket_name)
|
267
269
|
end
|
@@ -273,10 +275,13 @@ module Paperclip
|
|
273
275
|
acl = @s3_permissions[style] || @s3_permissions[:default]
|
274
276
|
acl = acl.call(self, style) if acl.respond_to?(:call)
|
275
277
|
write_options = {
|
276
|
-
:content_type => file.content_type
|
278
|
+
:content_type => file.content_type,
|
277
279
|
:acl => acl
|
278
280
|
}
|
279
281
|
write_options[:metadata] = @s3_metadata unless @s3_metadata.empty?
|
282
|
+
unless @s3_server_side_encryption.blank?
|
283
|
+
write_options[:server_side_encryption] = @s3_server_side_encryption
|
284
|
+
end
|
280
285
|
write_options.merge!(@s3_headers)
|
281
286
|
s3_object(style).write(file, write_options)
|
282
287
|
rescue AWS::S3::Errors::NoSuchBucket => e
|
@@ -302,6 +307,17 @@ module Paperclip
|
|
302
307
|
@queued_for_delete = []
|
303
308
|
end
|
304
309
|
|
310
|
+
def copy_to_local_file(style, local_dest_path)
|
311
|
+
log("copying #{path(style)} to local file #{local_dest_path}")
|
312
|
+
local_file = ::File.open(local_dest_path, 'wb')
|
313
|
+
file = s3_object(style)
|
314
|
+
local_file.write(file.read)
|
315
|
+
local_file.close
|
316
|
+
rescue AWS::Errors::Base => e
|
317
|
+
warn("#{e} - cannot copy #{path(style)} to local file #{local_dest_path}")
|
318
|
+
false
|
319
|
+
end
|
320
|
+
|
305
321
|
def find_credentials creds
|
306
322
|
case creds
|
307
323
|
when File
|
@@ -311,19 +327,11 @@ module Paperclip
|
|
311
327
|
when Hash
|
312
328
|
creds
|
313
329
|
else
|
314
|
-
raise ArgumentError, "Credentials are not a path, file, or hash."
|
330
|
+
raise ArgumentError, "Credentials are not a path, file, proc, or hash."
|
315
331
|
end
|
316
332
|
end
|
317
333
|
private :find_credentials
|
318
334
|
|
319
|
-
def establish_connection!
|
320
|
-
@connection ||= AWS::S3::Base.establish_connection!( @s3_options.merge(
|
321
|
-
:access_key_id => s3_credentials[:access_key_id],
|
322
|
-
:secret_access_key => s3_credentials[:secret_access_key]
|
323
|
-
))
|
324
|
-
end
|
325
|
-
private :establish_connection!
|
326
|
-
|
327
335
|
def use_secure_protocol?(style_name)
|
328
336
|
s3_protocol(style_name) == "https"
|
329
337
|
end
|