carrierwave-aliyun 1.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f6d5d5c0acc30b46d90292f4a90c05e90667bdbf40ec97b279342aa215a4f2ff
4
- data.tar.gz: f3b67cdf10f5800c250dafce535a6df95951c6c967e825f18fc3a656fa35268f
3
+ metadata.gz: 03a96d213f40d85c4e9cb135f1e32490fd3dcd2c38e1fe4c5fb866a0c06f8813
4
+ data.tar.gz: 372720e762645aed633542bce67a177b1718a1282ddf0012ca8d52eab554718d
5
5
  SHA512:
6
- metadata.gz: 4d0ba7b297d56905fdb8d24697e02e7ba56f89c0ea91ea7f73784746f404d2a7de2d0161c1a9b9b70c6e66050247ecc0828ce2396bccfa25ab24bd49ba11499c
7
- data.tar.gz: 9a6ee10ee4fb3299e9ef3170f1b4e41bc32d5137ee601295b2fed394cc060148f371835519db6af16bc5e6bf0f3be6164b4462b7fba202929505fe0d21562bf6
6
+ metadata.gz: a4957fb8b0998385cd932c142688cfd6dd8a2d9a971822a0fbf345e26382f2b44055e9a68e59a6ebc9c2ffae64a225eac6e30b97e43c4499ba177684982d38c0
7
+ data.tar.gz: 808b8d986b14cf9fcc25fd551c752a81e55bf59cd42db1b08b3c124a0de920254ea1f79fa5ca91a6c45ace1078716c097579f15f824edfa1117f5229a1b0c6db
@@ -1,3 +1,25 @@
1
+ ## 1.2.1
2
+
3
+ - 实现 `size` 方法,修正更新图片数组时,新上传的图片会取代旧图片的问题。(#73)
4
+
5
+ ## 1.2.0
6
+
7
+ - 整理修复 OSS 文件访问 URL 的生成方式,去掉 img host,保持和最新 OSS API 一样的逻辑。
8
+ - 生成 URL 的时候,不再强制替换为 https,保持 `aliyun_host` 的配置;
9
+
10
+ ## 1.1.2
11
+
12
+ - 修正 aliyun-sdk 0.7.0 以上 Thumb URL 生成的支持;
13
+ - Requirement aliyun-sdk >= 0.7.0;
14
+
15
+ ## 1.1.2
16
+
17
+ - 修正废弃调用方式,避免在 Ruby 2.7 里面出现 warning.
18
+
19
+ ## 1.1.1
20
+
21
+ - 对于 CarrierWave 的 cache 机制正确支持;
22
+
1
23
  ## 1.1.0
2
24
 
3
25
  - 支持 CarrierWave 2.0;
@@ -3,12 +3,12 @@
3
3
  module CarrierWave
4
4
  module Aliyun
5
5
  class Bucket
6
- PATH_PREFIX = %r{^/}
6
+ PATH_PREFIX = %r{^/}.freeze
7
7
  CHUNK_SIZE = 1024 * 1024
8
8
 
9
9
  attr_reader :access_key_id, :access_key_secret, :bucket, :region, :mode, :host
10
10
 
11
- attr_reader :endpoint, :img_endpoint, :upload_endpoint
11
+ attr_reader :endpoint, :upload_endpoint, :get_endpoint
12
12
 
13
13
  def initialize(uploader)
14
14
  if uploader.aliyun_area.present?
@@ -16,7 +16,7 @@ module CarrierWave
16
16
  uploader.aliyun_region ||= uploader.aliyun_area
17
17
  end
18
18
 
19
- if uploader.aliyun_private_read != nil
19
+ unless uploader.aliyun_private_read.nil?
20
20
  ActiveSupport::Deprecation.warn(%(config.aliyun_private_read will deprecation in carrierwave-aliyun 1.1.0, please use `aliyun_mode = :private` instead.))
21
21
  uploader.aliyun_mode ||= uploader.aliyun_private_read ? :private : :public
22
22
  end
@@ -38,15 +38,15 @@ module CarrierWave
38
38
  @mode = (uploader.aliyun_mode || :public).to_sym
39
39
 
40
40
  # Host for get request
41
- @host = uploader.aliyun_host || "https://#{self.bucket}.oss-#{self.region}.aliyuncs.com"
41
+ @endpoint = "https://#{bucket}.oss-#{region}.aliyuncs.com"
42
+ @host = uploader.aliyun_host || @endpoint
42
43
 
43
44
  unless @host.include?("//")
44
- raise "config.aliyun_host requirement include // http:// or https://, but you give: #{self.host}"
45
+ raise "config.aliyun_host requirement include // http:// or https://, but you give: #{host}"
45
46
  end
46
47
 
47
- @endpoint = "https://oss-#{self.region}.aliyuncs.com"
48
- @upload_endpoint = uploader.aliyun_internal == true ? "https://oss-#{self.region}-internal.aliyuncs.com" : @endpoint
49
- @img_endpoint = "https://img-#{self.region}.aliyuncs.com"
48
+ @get_endpoint = "https://oss-#{region}.aliyuncs.com"
49
+ @upload_endpoint = uploader.aliyun_internal == true ? "https://oss-#{region}-internal.aliyuncs.com" : "https://oss-#{region}.aliyuncs.com"
50
50
  end
51
51
 
52
52
  # 上传文件
@@ -70,11 +70,18 @@ module CarrierWave
70
70
  stream << file.read(CHUNK_SIZE) until file.eof?
71
71
  end
72
72
  path_to_url(path)
73
- rescue => e
73
+ rescue StandardError => e
74
74
  raise "Put file failed: #{e}"
75
75
  end
76
76
  end
77
77
 
78
+ def copy_object(source, dest)
79
+ source = source.sub(PATH_PREFIX, "")
80
+ dest = dest.sub(PATH_PREFIX, "")
81
+
82
+ oss_upload_client.copy_object(source, dest)
83
+ end
84
+
78
85
  # 读取文件
79
86
  # params:
80
87
  # - path - remote 存储路径
@@ -88,7 +95,7 @@ module CarrierWave
88
95
  end
89
96
 
90
97
  [obj, chunk_buff.join("")]
91
- rescue => e
98
+ rescue StandardError => e
92
99
  raise "Get content faild: #{e}"
93
100
  end
94
101
 
@@ -103,62 +110,60 @@ module CarrierWave
103
110
  path = path.sub(PATH_PREFIX, "")
104
111
  oss_upload_client.delete_object(path)
105
112
  path_to_url(path)
106
- rescue => e
113
+ rescue StandardError => e
107
114
  raise "Delete failed: #{e}"
108
115
  end
109
116
 
110
117
  ##
111
118
  # 根据配置返回完整的上传文件的访问地址
112
119
  def path_to_url(path, thumb: nil)
113
- path = path.sub(PATH_PREFIX, "")
114
-
115
- if thumb
116
- [self.host, [path, thumb].join("")].join("/")
117
- else
118
- [self.host, path].join("/")
119
- end
120
+ get_url(path, thumb: thumb)
120
121
  end
121
122
 
122
123
  # 私有空间访问地址,会带上实时算出的 token 信息
123
124
  # 有效期 15 minutes
124
125
  def private_get_url(path, thumb: nil)
126
+ get_url(path, private: true, thumb: thumb)
127
+ end
128
+
129
+ def get_url(path, private: false, thumb: nil)
125
130
  path = path.sub(PATH_PREFIX, "")
126
131
 
127
- url = if thumb
128
- img_client.object_url([path, thumb].join(""), expiry: 15.minutes)
132
+ url = if thumb&.start_with?("?")
133
+ # foo.jpg?x-oss-process=image/resize,h_100
134
+ parameters = { "x-oss-process" => thumb.split("=").last }
135
+ oss_client.object_url(path, private, 15.minutes, parameters)
129
136
  else
130
- oss_client.object_url(path, expiry: 15.minutes)
137
+ oss_client.object_url(path, private, 15.minutes)
131
138
  end
132
139
 
133
- url.sub("http://", "https://")
140
+ unless private
141
+ url = [url, thumb].join("") unless thumb&.start_with?("?")
142
+ end
143
+
144
+ url.sub(endpoint, host)
134
145
  end
135
146
 
136
147
  def head(path)
137
- oss_client.get_object_meta(path)
148
+ path = path.sub(PATH_PREFIX, "")
149
+ oss_upload_client.get_object(path)
138
150
  end
139
151
 
140
152
  private
141
153
 
142
- def oss_client
143
- return @oss_client if defined?(@oss_client)
144
- client = ::Aliyun::OSS::Client.new(endpoint: self.endpoint,
145
- access_key_id: self.access_key_id, access_key_secret: self.access_key_secret)
146
- @oss_client = client.get_bucket(self.bucket)
147
- end
154
+ def oss_client
155
+ return @oss_client if defined?(@oss_client)
148
156
 
149
- def img_client
150
- return @img_client if defined?(@img_client)
151
- client = ::Aliyun::OSS::Client.new(endpoint: self.img_endpoint,
152
- access_key_id: self.access_key_id, access_key_secret: self.access_key_secret)
153
- @img_client = client.get_bucket(self.bucket)
154
- end
157
+ client = ::Aliyun::OSS::Client.new(endpoint: get_endpoint, access_key_id: access_key_id, access_key_secret: access_key_secret)
158
+ @oss_client = client.get_bucket(bucket)
159
+ end
155
160
 
156
- def oss_upload_client
157
- return @oss_upload_client if defined?(@oss_upload_client)
158
- client = ::Aliyun::OSS::Client.new(endpoint: self.upload_endpoint,
159
- access_key_id: self.access_key_id, access_key_secret: self.access_key_secret)
160
- @oss_upload_client = client.get_bucket(self.bucket)
161
- end
161
+ def oss_upload_client
162
+ return @oss_upload_client if defined?(@oss_upload_client)
163
+
164
+ client = ::Aliyun::OSS::Client.new(endpoint: upload_endpoint, access_key_id: access_key_id, access_key_secret: access_key_secret)
165
+ @oss_upload_client = client.get_bucket(bucket)
166
+ end
162
167
  end
163
168
  end
164
169
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module CarrierWave
4
4
  module Aliyun
5
- VERSION = "1.1.0"
5
+ VERSION = "1.2.1"
6
6
  end
7
7
  end
@@ -3,14 +3,14 @@
3
3
  module CarrierWave
4
4
  module Storage
5
5
  class Aliyun < Abstract
6
- def store!(file)
6
+ def store!(new_file)
7
7
  f = AliyunFile.new(uploader, self, uploader.store_path)
8
8
  headers = {
9
- content_type: file.content_type,
9
+ content_type: new_file.content_type,
10
10
  content_disposition: uploader.try(:content_disposition)
11
11
  }
12
12
 
13
- f.store(::File.open(file.file), headers)
13
+ f.store(new_file, headers)
14
14
  f
15
15
  end
16
16
 
@@ -18,19 +18,19 @@ module CarrierWave
18
18
  AliyunFile.new(uploader, self, uploader.store_path(identifier))
19
19
  end
20
20
 
21
- def cache!(file)
22
- f = AliyunFile.new(uploader, self, uploader.store_path)
21
+ def cache!(new_file)
22
+ f = AliyunFile.new(uploader, self, uploader.cache_path)
23
23
  headers = {
24
- content_type: file.content_type,
24
+ content_type: new_file.content_type,
25
25
  content_disposition: uploader.try(:content_disposition)
26
26
  }
27
27
 
28
- f.store(::File.open(file.file), headers)
28
+ f.store(new_file, headers)
29
29
  f
30
30
  end
31
31
 
32
32
  def retrieve_from_cache!(identifier)
33
- AliyunFile.new(uploader, self, uploader.store_path(identifier))
33
+ AliyunFile.new(uploader, self, uploader.cache_path(identifier))
34
34
  end
35
35
 
36
36
  def delete_dir!(path)
@@ -38,8 +38,21 @@ module CarrierWave
38
38
  end
39
39
 
40
40
  def clean_cache!(_seconds)
41
- raise 'use Object Lifecycle Management to clean the cache'
41
+ will_remove_keys = []
42
+ bucket.list_objects(prefix: uploader.cache_path).each do |file|
43
+ next unless file.is_a?(Object)
44
+ time = file.key.scan(/(\d+)-\d+-\d+(?:-\d+)?/).first.map { |t| t.to_i }
45
+ time = Time.at(*time)
46
+ will_remove_keys << item.key if time < (Time.now.utc - seconds)
47
+ end
48
+ bucket.batch_delete_objects(will_remove_keys)
42
49
  end
50
+
51
+ private
52
+
53
+ def bucket
54
+ @bucket ||= CarrierWave::Aliyun::Bucket.new(uploader)
55
+ end
43
56
  end
44
57
  end
45
58
  end
@@ -2,23 +2,37 @@
2
2
 
3
3
  module CarrierWave
4
4
  module Storage
5
- class AliyunFile < CarrierWave::SanitizedFile
6
- attr_reader :path
5
+ class AliyunFile
6
+ attr_writer :file
7
+ attr_reader :uploader, :path
8
+
9
+ alias_method :filename, :path
10
+ alias_method :identifier, :filename
7
11
 
8
12
  def initialize(uploader, base, path)
9
- @uploader = uploader
10
- @path = URI.encode(path)
11
- @base = base
13
+ @uploader, @path, @base = uploader, escape(path), base
14
+ end
15
+
16
+ def file
17
+ @file ||= bucket.get(path).try(:first)
18
+ end
19
+
20
+ def size
21
+ file.headers[:content_length].to_i rescue nil
22
+ end
23
+
24
+ def escape(path)
25
+ CGI.escape(path).gsub("%2F", "/")
12
26
  end
13
27
 
14
28
  def read
15
- object, body = bucket.get(@path)
29
+ object, body = bucket.get(path)
16
30
  @headers = object.headers
17
31
  body
18
32
  end
19
33
 
20
34
  def delete
21
- bucket.delete(@path)
35
+ bucket.delete(path)
22
36
  true
23
37
  rescue => e
24
38
  # If the file's not there, don't panic
@@ -33,9 +47,9 @@ module CarrierWave
33
47
  #
34
48
  def url(opts = {})
35
49
  if bucket.mode == :private
36
- bucket.private_get_url(@path, opts)
50
+ bucket.private_get_url(path, **opts)
37
51
  else
38
- bucket.path_to_url(@path, opts)
52
+ bucket.path_to_url(path, **opts)
39
53
  end
40
54
  end
41
55
 
@@ -49,22 +63,49 @@ module CarrierWave
49
63
 
50
64
  def store(new_file, headers = {})
51
65
  if new_file.is_a?(self.class)
52
- new_file.move_to(path)
66
+ new_file.copy_to(path)
53
67
  else
54
- bucket.put(@path, new_file, headers)
68
+ fog_file = new_file.to_file
69
+ bucket.put(path, fog_file, **headers)
70
+ fog_file.close if fog_file && !fog_file.closed?
55
71
  end
72
+ true
56
73
  end
57
74
 
58
75
  def headers
59
- @headers ||= {}
76
+ @headers ||= begin
77
+ obj = bucket.head(path)
78
+ obj.headers
79
+ end
80
+ end
81
+
82
+ def exists?
83
+ !!headers
84
+ end
85
+
86
+ def copy_to(new_path)
87
+ bucket.copy_object(path, new_path)
88
+ self.class.new(uploader, @base, new_path)
89
+ end
90
+
91
+ def extension
92
+ path_elements = path.split(".")
93
+ path_elements.last if path_elements.size > 1
94
+ end
95
+
96
+ def original_filename
97
+ return @original_filename if @original_filename
98
+ if @file && @file.respond_to?(:original_filename)
99
+ @file.original_filename
100
+ elsif path
101
+ ::File.basename(path)
102
+ end
60
103
  end
61
104
 
62
105
  private
63
106
 
64
107
  def bucket
65
- return @bucket if defined? @bucket
66
-
67
- @bucket = CarrierWave::Aliyun::Bucket.new(@uploader)
108
+ @bucket ||= CarrierWave::Aliyun::Bucket.new(uploader)
68
109
  end
69
110
  end
70
111
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: carrierwave-aliyun
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Lee
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-20 00:00:00.000000000 Z
11
+ date: 2021-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: carrierwave
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.6.0
33
+ version: 0.7.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 0.6.0
40
+ version: 0.7.0
41
41
  description: Aliyun OSS support for Carrierwave
42
42
  email:
43
43
  - huacnlee@gmail.com
@@ -57,7 +57,7 @@ homepage: https://github.com/huacnlee/carrierwave-aliyun
57
57
  licenses:
58
58
  - MIT
59
59
  metadata: {}
60
- post_install_message:
60
+ post_install_message:
61
61
  rdoc_options: []
62
62
  require_paths:
63
63
  - lib
@@ -72,8 +72,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
72
  - !ruby/object:Gem::Version
73
73
  version: '0'
74
74
  requirements: []
75
- rubygems_version: 3.0.3
76
- signing_key:
75
+ rubygems_version: 3.1.4
76
+ signing_key:
77
77
  specification_version: 4
78
78
  summary: Aliyun OSS support for Carrierwave
79
79
  test_files: []