-
Notifications
You must be signed in to change notification settings - Fork 287
/
camaleon_cms_aws_uploader.rb
154 lines (132 loc) · 5.78 KB
/
camaleon_cms_aws_uploader.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
class CamaleonCmsAwsUploader < CamaleonCmsUploader
def after_initialize
@cloudfront = @aws_settings[:cloud_front] || @current_site.get_option('filesystem_s3_cloudfront')
@aws_region = @aws_settings[:region] || @current_site.get_option('filesystem_region', 'us-west-2')
@aws_akey = @aws_settings[:access_key] || @current_site.get_option('filesystem_s3_access_key')
@aws_asecret = @aws_settings[:secret_key] || @current_site.get_option('filesystem_s3_secret_key')
@aws_bucket = @aws_settings[:bucket] || @current_site.get_option('filesystem_s3_bucket_name')
@aws_endpoint = @aws_settings[:endpoint] || @current_site.get_option('filesystem_s3_endpoint')
@aws_settings[:aws_file_upload_settings] ||= ->(settings) { settings }
@aws_settings[:aws_file_read_settings] ||= ->(data, _s3_file) { data }
end
def setup_private_folder
return unless is_private_uploader?
add_folder(PRIVATE_DIRECTORY)
@aws_settings['inner_folder'] = "#{@aws_settings['inner_folder']}/#{PRIVATE_DIRECTORY}"
end
# recover all files from AWS and parse it to save into DB as cache
def browser_files
bucket.objects({ prefix: @aws_settings['inner_folder'].presence || nil }).each do |file|
next if File.dirname(file.key).split('/').pop == 'thumb'
cache_item(file_parse(file))
end
end
# load media files from a specific folder path
def objects(prefix = '/', sort = 'created_at')
if @aws_settings['inner_folder'].present?
prefix = "#{@aws_settings['inner_folder']}/#{prefix}".gsub('//', '/')
prefix = prefix[0..-2] if prefix.end_with?('/')
end
super(prefix, sort)
end
def fetch_file(file_name)
return file_name if file_exists?(file_name)
return file_name if bucket.object(file_name).download_file(file_name) && file_exists?(file_name)
{ error: 'File not found' }
end
# parse an AWS file into custom file_object
def file_parse(s3_file)
key = s3_file.is_a?(String) ? s3_file : s3_file.key
key = key.cama_fix_media_key
is_dir = s3_file.is_a?(String) || File.extname(key) == ''
url = if is_private_uploader?
is_dir ? '' : File.basename(key)
elsif is_dir
''
else
(@cloudfront.present? ? File.join(@cloudfront, key) : s3_file.public_url)
end
res = {
'name' => File.basename(key),
'folder_path' => File.dirname(key),
'url' => url,
'is_folder' => is_dir,
'file_size' => is_dir ? 0 : s3_file.size.round(2),
'thumb' => '',
'file_type' => is_dir ? '' : self.class.get_file_format(key),
'created_at' => is_dir ? '' : s3_file.last_modified,
'dimension' => ''
}.with_indifferent_access
if res['file_type'] == 'image' && File.extname(res['name']).downcase != '.gif'
res['thumb'] =
version_path(res['url']).sub('.svg',
'.jpg')
end
res['key'] = File.join(res['folder_path'], res['name'])
@aws_settings[:aws_file_read_settings].call(res, s3_file)
end
# add a file object or file path into AWS server
# :key => (String) key of the file ot save in AWS
# :args => (HASH) {same_name: false, is_thumb: false}, where:
# - same_name: false => avoid to overwrite an existent file with same key and search for an available key
# - is_thumb: true => if this file is a thumbnail of an uploaded file
def add_file(uploaded_io_or_file_path, key, args = {})
args = { same_name: false, is_thumb: false }.merge(args)
res = nil
key = "#{@aws_settings['inner_folder']}/#{key}" if @aws_settings['inner_folder'].present? && !args[:is_thumb]
key = key.cama_fix_media_key
key = search_new_key(key) unless args[:same_name]
if @instance # private hook to upload files by different way, add file data into result_data
_args = { result_data: nil, file: uploaded_io_or_file_path, key: key, args: args, klass: self }
@instance.hooks_run('uploader_aws_before_upload', _args)
return _args[:result_data] if _args[:result_data].present?
end
s3_file = bucket.object(key.slice(1..-1))
s3_file.upload_file(
uploaded_io_or_file_path.is_a?(String) ? uploaded_io_or_file_path : uploaded_io_or_file_path.path, @aws_settings[:aws_file_upload_settings].call({ acl: 'public-read' })
)
res = cache_item(file_parse(s3_file)) unless args[:is_thumb]
res
end
# add new folder to AWS with :key
def add_folder(key)
return { error: 'Invalid folder path' } unless valid_folder_path?(key)
key = "#{@aws_settings['inner_folder']}/#{key}" if @aws_settings['inner_folder'].present?
key = key.cama_fix_media_key
s3_file = bucket.object(key.slice(1..-1) << '/')
s3_file.put(body: nil)
cache_item(file_parse(s3_file))
end
# delete a folder in AWS with :key
def delete_folder(key)
key = "#{@aws_settings['inner_folder']}/#{key}" if @aws_settings['inner_folder'].present?
key = key.cama_fix_media_key
bucket.objects(prefix: key.slice(1..-1) << '/').delete
get_media_collection.find_by_key(key).take.destroy
end
# delete a file in AWS with :key
def delete_file(key)
key = "#{@aws_settings['inner_folder']}/#{key}" if @aws_settings['inner_folder'].present?
key = key.cama_fix_media_key
begin
bucket.object(key.slice(1..-1)).delete
rescue StandardError
''
end
@instance.hooks_run('after_delete', key)
get_media_collection.find_by_key(key).take.destroy
end
# initialize a bucket with AWS configurations
# return: (AWS Bucket object)
def bucket
@bucket ||= lambda {
Aws.config.update({ region: @aws_region, credentials: Aws::Credentials.new(@aws_akey, @aws_asecret) })
s3 = Aws::S3::Resource.new(resource_parameters)
s3.bucket(@aws_bucket)
}.call
end
def resource_parameters
return {} if @aws_endpoint.blank?
{ endpoint: @aws_endpoint }
end
end