paperclip_oss_storage 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|