paperclip_oss_storage 0.0.2 → 0.0.3
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 +4 -4
- data/lib/aliyun/connection.rb +171 -0
- data/lib/paperclip/storage/aliyun.rb +44 -0
- data/lib/paperclip_oss_storage/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b6f6609164daccce0a8193a6c45146baf9bcde65
|
4
|
+
data.tar.gz: e97c77aa5a4634c4c0862fd53f4fa76e8879e7d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 06c66a0fbef1bc638c40213c7073e51d10ef9e7d0c625d196a8d5c11c702523142bb4af2d3cf97e0fa20f908993671264000bdf70c29d91df6e146c2485aad1d
|
7
|
+
data.tar.gz: 2a1068fb172c4be299035e5876776c070bfdb8c77f99458bd0041515cc210a81888416b7eefbcf94d5ed3f3332e53f4ead39743e9381127a077afb127559c13b
|
@@ -0,0 +1,171 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'digest/hmac'
|
4
|
+
require 'digest/md5'
|
5
|
+
require "rest-client"
|
6
|
+
require "base64"
|
7
|
+
require 'uri'
|
8
|
+
|
9
|
+
module Aliyun
|
10
|
+
class Connection
|
11
|
+
def initialize(options = Paperclip::Attachment.default_options[:aliyun])
|
12
|
+
@aliyun_access_id = options[:access_id]
|
13
|
+
@aliyun_access_key = options[:access_key]
|
14
|
+
@aliyun_bucket = options[:bucket]
|
15
|
+
|
16
|
+
data_centre = options[:data_centre].to_s.downcase == 'qingdao' ? 'qingdao' : 'hangzhou'
|
17
|
+
internal = options[:internal] == true ? true : false
|
18
|
+
@aliyun_data_centre = "oss-cn-#{data_centre}#{internal ? '-internal' : nil}.aliyuncs.com"
|
19
|
+
|
20
|
+
@aliyun_upload_host = "#{@aliyun_bucket}.#{@aliyun_data_centre}"
|
21
|
+
|
22
|
+
@aliyun_host = options[:host] || @aliyun_upload_host
|
23
|
+
end
|
24
|
+
|
25
|
+
def fetch_file_host
|
26
|
+
@aliyun_host
|
27
|
+
end
|
28
|
+
|
29
|
+
=begin rdoc
|
30
|
+
上传文件
|
31
|
+
|
32
|
+
== 参数:
|
33
|
+
- path - remote 存储路径
|
34
|
+
- file - 需要上传文件的 File 对象
|
35
|
+
- options:
|
36
|
+
- content_type - 上传文件的 MimeType,默认 `image/jpg`
|
37
|
+
|
38
|
+
== 返回值:
|
39
|
+
图片的下载地址
|
40
|
+
=end
|
41
|
+
def put(path, file, options={})
|
42
|
+
path = format_path(path)
|
43
|
+
bucket_path = get_bucket_path(path)
|
44
|
+
content_md5 = Digest::MD5.file(file)
|
45
|
+
content_type = options[:content_type] || "image/jpg"
|
46
|
+
date = gmtdate
|
47
|
+
url = path_to_url(path)
|
48
|
+
auth_sign = sign("PUT", bucket_path, content_md5, content_type, date)
|
49
|
+
headers = {
|
50
|
+
"Authorization" => auth_sign,
|
51
|
+
"Content-Type" => content_type,
|
52
|
+
"Content-Length" => file.size,
|
53
|
+
"Date" => date,
|
54
|
+
"Host" => @aliyun_upload_host,
|
55
|
+
"Expect" => "100-Continue"
|
56
|
+
}
|
57
|
+
response = RestClient.put(URI.encode(url), file, headers)
|
58
|
+
response.code == 200 ? path_to_url(path) : nil
|
59
|
+
end
|
60
|
+
|
61
|
+
=begin rdoc
|
62
|
+
删除 Remote 的文件
|
63
|
+
|
64
|
+
== 参数:
|
65
|
+
- path - remote 存储路径
|
66
|
+
|
67
|
+
== 返回值:
|
68
|
+
图片的下载地址
|
69
|
+
=end
|
70
|
+
def delete(path)
|
71
|
+
path = format_path(path)
|
72
|
+
bucket_path = get_bucket_path(path)
|
73
|
+
date = gmtdate
|
74
|
+
headers = {
|
75
|
+
"Host" => @aliyun_upload_host,
|
76
|
+
"Date" => date,
|
77
|
+
"Authorization" => sign("DELETE", bucket_path, "", "" ,date)
|
78
|
+
}
|
79
|
+
url = path_to_url(path)
|
80
|
+
response = RestClient.delete(URI.encode(url), headers)
|
81
|
+
response.code == 204 ? url : nil
|
82
|
+
end
|
83
|
+
|
84
|
+
=begin rdoc
|
85
|
+
下载 Remote 的文件
|
86
|
+
|
87
|
+
== 参数:
|
88
|
+
- path - remote 存储路径
|
89
|
+
|
90
|
+
== 返回值:
|
91
|
+
请求的图片的数据流
|
92
|
+
=end
|
93
|
+
def get(path)
|
94
|
+
path = format_path(path)
|
95
|
+
bucket_path = get_bucket_path(path)
|
96
|
+
date = gmtdate
|
97
|
+
headers = {
|
98
|
+
"Host" => @aliyun_upload_host,
|
99
|
+
"Date" => date,
|
100
|
+
"Authorization" => sign("GET", bucket_path, "", "" ,date)
|
101
|
+
}
|
102
|
+
url = path_to_url(path)
|
103
|
+
response = RestClient.get(URI.encode(url), headers)
|
104
|
+
response.body
|
105
|
+
end
|
106
|
+
|
107
|
+
=begin rdoc
|
108
|
+
检查远程服务器是否已存在指定文件
|
109
|
+
|
110
|
+
== 参数:
|
111
|
+
- path - remote 存储路径
|
112
|
+
|
113
|
+
== 返回值:
|
114
|
+
true/false
|
115
|
+
=end
|
116
|
+
def exists?(path)
|
117
|
+
path = format_path(path)
|
118
|
+
bucket_path = get_bucket_path(path)
|
119
|
+
date = gmtdate
|
120
|
+
headers = {
|
121
|
+
"Host" => @aliyun_upload_host,
|
122
|
+
"Date" => date,
|
123
|
+
"Authorization" => sign("HEAD", bucket_path, "", "", date)
|
124
|
+
}
|
125
|
+
url = path_to_url(path)
|
126
|
+
|
127
|
+
# rest_client will throw exception if requested resource not found
|
128
|
+
begin
|
129
|
+
response = RestClient.head(URI.encode(url), headers)
|
130
|
+
rescue RestClient::ResourceNotFound
|
131
|
+
return false
|
132
|
+
end
|
133
|
+
|
134
|
+
true
|
135
|
+
end
|
136
|
+
|
137
|
+
##
|
138
|
+
# 阿里云需要的 GMT 时间格式
|
139
|
+
def gmtdate
|
140
|
+
Time.now.gmtime.strftime("%a, %d %b %Y %H:%M:%S GMT")
|
141
|
+
end
|
142
|
+
|
143
|
+
def format_path(path)
|
144
|
+
return "" if path.blank?
|
145
|
+
path.gsub!(/^\/+/,"")
|
146
|
+
|
147
|
+
path
|
148
|
+
end
|
149
|
+
|
150
|
+
def get_bucket_path(path)
|
151
|
+
[@aliyun_bucket,path].join("/")
|
152
|
+
end
|
153
|
+
|
154
|
+
##
|
155
|
+
# 根据配置返回完整的上传文件的访问地址
|
156
|
+
def path_to_url(path)
|
157
|
+
"http://#{fetch_file_host}/#{path}"
|
158
|
+
end
|
159
|
+
|
160
|
+
private
|
161
|
+
def sign(verb, path, content_md5 = '', content_type = '', date)
|
162
|
+
canonicalized_oss_headers = ''
|
163
|
+
canonicalized_resource = "/#{path}"
|
164
|
+
string_to_sign = "#{verb}\n\n#{content_type}\n#{date}\n#{canonicalized_oss_headers}#{canonicalized_resource}"
|
165
|
+
digest = OpenSSL::Digest::Digest.new('sha1')
|
166
|
+
h = OpenSSL::HMAC.digest(digest, @aliyun_access_key, string_to_sign)
|
167
|
+
h = Base64.encode64(h)
|
168
|
+
"OSS #{@aliyun_access_id}:#{h}"
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Paperclip
|
2
|
+
module Storage
|
3
|
+
module Aliyun
|
4
|
+
def self.extended(base)
|
5
|
+
end
|
6
|
+
|
7
|
+
def exists?(style = default_style)
|
8
|
+
oss_connection.exists? path(style)
|
9
|
+
end
|
10
|
+
|
11
|
+
def flush_writes #:nodoc:
|
12
|
+
@queued_for_write.each do |style_name, file|
|
13
|
+
oss_connection.put path(style_name), (File.new file.path)
|
14
|
+
end
|
15
|
+
|
16
|
+
after_flush_writes
|
17
|
+
|
18
|
+
@queued_for_write = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def flush_deletes #:nodoc:
|
22
|
+
@queued_for_delete.each do |path|
|
23
|
+
oss_connection.delete path
|
24
|
+
end
|
25
|
+
|
26
|
+
@queued_for_delete = []
|
27
|
+
end
|
28
|
+
|
29
|
+
def copy_to_local_file(style = default_style, local_dest_path)
|
30
|
+
log("copying #{path(style)} to local file #{local_dest_path}")
|
31
|
+
local_file = ::File.open(local_dest_path, 'wb')
|
32
|
+
remote_file_str = oss_connection.get path(style)
|
33
|
+
local_file.write(remote_file_str)
|
34
|
+
local_file.close
|
35
|
+
end
|
36
|
+
|
37
|
+
def oss_connection
|
38
|
+
return @oss_connection if @oss_connection
|
39
|
+
|
40
|
+
@oss_connection ||= ::Aliyun::Connection.new
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paperclip_oss_storage
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elite
|
@@ -50,6 +50,8 @@ files:
|
|
50
50
|
- LICENSE.txt
|
51
51
|
- README.md
|
52
52
|
- Rakefile
|
53
|
+
- lib/aliyun/connection.rb
|
54
|
+
- lib/paperclip/storage/aliyun.rb
|
53
55
|
- lib/paperclip_oss_storage.rb
|
54
56
|
- lib/paperclip_oss_storage/version.rb
|
55
57
|
- paperclip_oss_storage.gemspec
|