carrierwave-aliyun-oss 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +1 -0
- data/.travis.yml +8 -0
- data/CHANGELOG.md +81 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +155 -0
- data/README.md +42 -0
- data/Rakefile +7 -0
- data/carrierwave-aliyun.gemspec +22 -0
- data/lib/carrierwave-aliyun.rb +13 -0
- data/lib/carrierwave/aliyun/configuration.rb +40 -0
- data/lib/carrierwave/aliyun/version.rb +5 -0
- data/lib/carrierwave/storage/aliyun.rb +227 -0
- data/spec/aliyun_spec.rb +70 -0
- data/spec/foo.gif +0 -0
- data/spec/foo.jpg +0 -0
- data/spec/foo.zip +0 -0
- data/spec/spec_helper.rb +43 -0
- data/spec/upload_spec.rb +119 -0
- metadata +97 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1f20e0cea2396c58f7841b1800d5b9bc4634247d
|
4
|
+
data.tar.gz: 67ff4a2898972cf36a4902fc28315d99b17bd60a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d30960df8a43f48ecc3bcb8adc349cbcea72f26f5d61a44b4eb38a895495bc09a5f2369ff7d7756ed3f978b43be9a21a518d565ade4b3cd8521db3896360c614
|
7
|
+
data.tar.gz: b24119fb93e151a72f3c1ee31138b712d33bf1108193b739f9f85946a70165ba69eb81318825fcc1d2921a792287f64fb348b445f5849df855d5a0cc5c77c2a0
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
## 0.4.4
|
2
|
+
|
3
|
+
- 修正对 Carrierwave master 版本的支持,它们[移除了](https://github.com/carrierwaveuploader/carrierwave/pull/1813) `carrierwave/processing/mime_types`;
|
4
|
+
|
5
|
+
## 0.4.3
|
6
|
+
|
7
|
+
- 修正私密空间下载地址算法的问题,导致偶尔会签名错误无法下载的问题;
|
8
|
+
|
9
|
+
## 0.4.2
|
10
|
+
|
11
|
+
- `config.aliyun_host` 现在支持配置 //you-host.com,以便同时支持 http 和 https。
|
12
|
+
|
13
|
+
## 0.4.1
|
14
|
+
|
15
|
+
- 由于 aliyun-oss-sdk 目前不支持 internal 上传,暂时去掉,以免签名错误。
|
16
|
+
|
17
|
+
## 0.4.0
|
18
|
+
|
19
|
+
- 采用 aliyun-oss-sdk 来作为上传后端,不再依赖 rest-client,不再内部实现上传逻辑;
|
20
|
+
- 增加 `config.aliyun_private_read` 配置项,开启以后,返回的 @user.avatar.url 将会是带 Token 和有效期的 URL,可以用于访问私有读取空间的文件;
|
21
|
+
- 去掉 `config.aliyun_upload_host` 配置项,删除了阿里内部的支持,以后请用 0.3.x 版本;
|
22
|
+
|
23
|
+
## 0.3.6
|
24
|
+
|
25
|
+
- 修正上传中文文件名无法成功的问题;
|
26
|
+
|
27
|
+
## 0.3.5
|
28
|
+
|
29
|
+
- CarrierWave::Storage::Aliyun::File 继承 CarrierWave::SanitizedFile 以实现一些方法;
|
30
|
+
|
31
|
+
## 0.3.4
|
32
|
+
|
33
|
+
- Use OpenSSL::HMAC with Ruby 2.2.0.
|
34
|
+
|
35
|
+
## 0.3.3
|
36
|
+
|
37
|
+
- 增加 `config.aliyun_upload_host`, 以便有需要的时候,可以自由修改上传的 host.
|
38
|
+
|
39
|
+
## 0.3.2
|
40
|
+
|
41
|
+
- 请注意 `config.aliyun_host` 要求修改带 HTTP 协议,以便支持设置 http:// 或 https://.
|
42
|
+
|
43
|
+
## 0.3.1
|
44
|
+
|
45
|
+
- 修复当文件名中包含了 "+",在 OSS 中上传会遇到签名不对应的问题;
|
46
|
+
|
47
|
+
## 0.3.0
|
48
|
+
|
49
|
+
- 新增 `aliyun_area` 参数,用于配置 OSS 所在地区数据中心;
|
50
|
+
|
51
|
+
## 0.2.1
|
52
|
+
|
53
|
+
- 避免计算上传文件的时候读取所有内容到内存,之前的做法对于大文件会耗费过多的内存;
|
54
|
+
- Carrierwave::Storage::Aliyum::Connection 的 put 方法接口变化,file 现在应该传一个 File 的实例。
|
55
|
+
|
56
|
+
## 0.2.0
|
57
|
+
|
58
|
+
- Aliyun OSS 新的[三级域名规则支持](http://bbs.aliyun.com/read.php?tid=139226) by [chaixl](https://github.com/chaixl)
|
59
|
+
- 注意! 如果你之前使用 0.1.5 一下的版本,你可能需要调整一下你的自定义域名的 CNAME 解析,阿里云新的 URL 结构变化(少了 Bucket 一层目录),当然你也可以选择不要升级,之前 0.1.5 版本是稳定的。
|
60
|
+
|
61
|
+
## 0.1.5
|
62
|
+
|
63
|
+
- 自定义域名支持
|
64
|
+
|
65
|
+
## 0.1.3
|
66
|
+
|
67
|
+
- delete 接口加入。
|
68
|
+
- 支持 Carriewave 自动在更新上传文件的时候删除老文件(比如,用户重新上传头像,老头像图片文件将会被 CarrierWave 删除)。
|
69
|
+
|
70
|
+
## 0.1.2
|
71
|
+
|
72
|
+
- 修正 content_type 的支持,自动用原始文件的 content_type,以免上传 zip 之类的文件以后无法下载.
|
73
|
+
|
74
|
+
## 0.1.1
|
75
|
+
|
76
|
+
- 修改 Aliyun OSS 的请求地址.
|
77
|
+
- 加入可选项,使用 Aliyun 内部地址调用上传,以提高内部网络使用的速度.
|
78
|
+
|
79
|
+
## 0.1.0
|
80
|
+
|
81
|
+
- 功能实现.
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
carrierwave-aliyun (0.4.4)
|
5
|
+
aliyun-sdk (>= 0.4.0)
|
6
|
+
carrierwave (>= 0.5.7)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
actionmailer (4.2.0)
|
12
|
+
actionpack (= 4.2.0)
|
13
|
+
actionview (= 4.2.0)
|
14
|
+
activejob (= 4.2.0)
|
15
|
+
mail (~> 2.5, >= 2.5.4)
|
16
|
+
rails-dom-testing (~> 1.0, >= 1.0.5)
|
17
|
+
actionpack (4.2.0)
|
18
|
+
actionview (= 4.2.0)
|
19
|
+
activesupport (= 4.2.0)
|
20
|
+
rack (~> 1.6.0)
|
21
|
+
rack-test (~> 0.6.2)
|
22
|
+
rails-dom-testing (~> 1.0, >= 1.0.5)
|
23
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.1)
|
24
|
+
actionview (4.2.0)
|
25
|
+
activesupport (= 4.2.0)
|
26
|
+
builder (~> 3.1)
|
27
|
+
erubis (~> 2.7.0)
|
28
|
+
rails-dom-testing (~> 1.0, >= 1.0.5)
|
29
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.1)
|
30
|
+
activejob (4.2.0)
|
31
|
+
activesupport (= 4.2.0)
|
32
|
+
globalid (>= 0.3.0)
|
33
|
+
activemodel (4.2.0)
|
34
|
+
activesupport (= 4.2.0)
|
35
|
+
builder (~> 3.1)
|
36
|
+
activerecord (4.2.0)
|
37
|
+
activemodel (= 4.2.0)
|
38
|
+
activesupport (= 4.2.0)
|
39
|
+
arel (~> 6.0)
|
40
|
+
activesupport (4.2.0)
|
41
|
+
i18n (~> 0.7)
|
42
|
+
json (~> 1.7, >= 1.7.7)
|
43
|
+
minitest (~> 5.1)
|
44
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
45
|
+
tzinfo (~> 1.1)
|
46
|
+
aliyun-sdk (0.4.0)
|
47
|
+
nokogiri (~> 1.6)
|
48
|
+
rest-client (~> 1.8)
|
49
|
+
arel (6.0.3)
|
50
|
+
builder (3.2.2)
|
51
|
+
carrierwave (0.11.2)
|
52
|
+
activemodel (>= 3.2.0)
|
53
|
+
activesupport (>= 3.2.0)
|
54
|
+
json (>= 1.7)
|
55
|
+
mime-types (>= 1.16)
|
56
|
+
mimemagic (>= 0.3.0)
|
57
|
+
concurrent-ruby (1.0.1)
|
58
|
+
diff-lcs (1.2.5)
|
59
|
+
domain_name (0.5.20160310)
|
60
|
+
unf (>= 0.0.5, < 1.0.0)
|
61
|
+
erubis (2.7.0)
|
62
|
+
globalid (0.3.6)
|
63
|
+
activesupport (>= 4.1.0)
|
64
|
+
http-cookie (1.0.2)
|
65
|
+
domain_name (~> 0.5)
|
66
|
+
i18n (0.7.0)
|
67
|
+
json (1.8.3)
|
68
|
+
loofah (2.0.3)
|
69
|
+
nokogiri (>= 1.5.9)
|
70
|
+
mail (2.6.3)
|
71
|
+
mime-types (>= 1.16, < 3)
|
72
|
+
mime-types (2.99.1)
|
73
|
+
mimemagic (0.3.1)
|
74
|
+
mini_magick (4.4.0)
|
75
|
+
mini_portile2 (2.0.0)
|
76
|
+
minitest (5.8.4)
|
77
|
+
netrc (0.11.0)
|
78
|
+
nokogiri (1.6.7.2)
|
79
|
+
mini_portile2 (~> 2.0.0.rc2)
|
80
|
+
rack (1.6.4)
|
81
|
+
rack-test (0.6.3)
|
82
|
+
rack (>= 1.0)
|
83
|
+
rails (4.2.0)
|
84
|
+
actionmailer (= 4.2.0)
|
85
|
+
actionpack (= 4.2.0)
|
86
|
+
actionview (= 4.2.0)
|
87
|
+
activejob (= 4.2.0)
|
88
|
+
activemodel (= 4.2.0)
|
89
|
+
activerecord (= 4.2.0)
|
90
|
+
activesupport (= 4.2.0)
|
91
|
+
bundler (>= 1.3.0, < 2.0)
|
92
|
+
railties (= 4.2.0)
|
93
|
+
sprockets-rails
|
94
|
+
rails-deprecated_sanitizer (1.0.3)
|
95
|
+
activesupport (>= 4.2.0.alpha)
|
96
|
+
rails-dom-testing (1.0.7)
|
97
|
+
activesupport (>= 4.2.0.beta, < 5.0)
|
98
|
+
nokogiri (~> 1.6.0)
|
99
|
+
rails-deprecated_sanitizer (>= 1.0.1)
|
100
|
+
rails-html-sanitizer (1.0.3)
|
101
|
+
loofah (~> 2.0)
|
102
|
+
railties (4.2.0)
|
103
|
+
actionpack (= 4.2.0)
|
104
|
+
activesupport (= 4.2.0)
|
105
|
+
rake (>= 0.8.7)
|
106
|
+
thor (>= 0.18.1, < 2.0)
|
107
|
+
rake (10.5.0)
|
108
|
+
rest-client (1.8.0)
|
109
|
+
http-cookie (>= 1.0.2, < 2.0)
|
110
|
+
mime-types (>= 1.16, < 3.0)
|
111
|
+
netrc (~> 0.7)
|
112
|
+
rspec (3.4.0)
|
113
|
+
rspec-core (~> 3.4.0)
|
114
|
+
rspec-expectations (~> 3.4.0)
|
115
|
+
rspec-mocks (~> 3.4.0)
|
116
|
+
rspec-core (3.4.3)
|
117
|
+
rspec-support (~> 3.4.0)
|
118
|
+
rspec-expectations (3.4.0)
|
119
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
120
|
+
rspec-support (~> 3.4.0)
|
121
|
+
rspec-mocks (3.4.1)
|
122
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
123
|
+
rspec-support (~> 3.4.0)
|
124
|
+
rspec-support (3.4.1)
|
125
|
+
sprockets (3.5.2)
|
126
|
+
concurrent-ruby (~> 1.0)
|
127
|
+
rack (> 1, < 3)
|
128
|
+
sprockets-rails (3.0.4)
|
129
|
+
actionpack (>= 4.0)
|
130
|
+
activesupport (>= 4.0)
|
131
|
+
sprockets (>= 3.0.0)
|
132
|
+
sqlite3 (1.3.11)
|
133
|
+
sqlite3-ruby (1.3.3)
|
134
|
+
sqlite3 (>= 1.3.3)
|
135
|
+
thor (0.19.1)
|
136
|
+
thread_safe (0.3.5)
|
137
|
+
tzinfo (1.2.2)
|
138
|
+
thread_safe (~> 0.1)
|
139
|
+
unf (0.1.4)
|
140
|
+
unf_ext
|
141
|
+
unf_ext (0.0.7.2)
|
142
|
+
|
143
|
+
PLATFORMS
|
144
|
+
ruby
|
145
|
+
|
146
|
+
DEPENDENCIES
|
147
|
+
carrierwave-aliyun!
|
148
|
+
mini_magick
|
149
|
+
rails (= 4.2.0)
|
150
|
+
rake
|
151
|
+
rspec
|
152
|
+
sqlite3-ruby
|
153
|
+
|
154
|
+
BUNDLED WITH
|
155
|
+
1.11.2
|
data/README.md
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# CarrierWave for Aliyun OSS
|
2
|
+
|
3
|
+
This gem adds support for [Aliyun OSS](http://oss.aliyun.com) to [CarrierWave](https://github.com/jnicklas/carrierwave/)
|
4
|
+
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/carrierwave-aliyun.svg)](https://rubygems.org/gems/carrierwave-aliyun) [![Build Status](https://travis-ci.org/huacnlee/carrierwave-aliyun.svg?branch=master)](https://travis-ci.org/huacnlee/carrierwave-aliyun)
|
6
|
+
|
7
|
+
> NOTE: 此 Gem 是一个 CarrierWave 的组件,你需要配合 CarrierWave 一起使用,如果你需要直接用 Aliyun OSS,可以尝试用 [aliyun-oss-ruby-sdk](https://github.com/aliyun-beta/aliyun-oss-ruby-sdk) 这个 Gem。
|
8
|
+
|
9
|
+
> NOTE: 20160604 修改依赖aliyun-oss-ruby-sdk为aliyun-sdk(>=0.4.0),以支持config.aliyun_internal配置
|
10
|
+
|
11
|
+
## Using Bundler
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'carrierwave-aliyun'
|
15
|
+
```
|
16
|
+
|
17
|
+
## Configuration
|
18
|
+
|
19
|
+
创建这么个脚本 `config/initializers/carrierwave.rb` 填入下面的代码,并修改对应的配置:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
CarrierWave.configure do |config|
|
23
|
+
config.storage = :aliyun
|
24
|
+
config.aliyun_access_id = "xxxxxx"
|
25
|
+
config.aliyun_access_key = 'xxxxxx'
|
26
|
+
# 你需要在 Aliyum OSS 上面提前创建一个 Bucket
|
27
|
+
config.aliyun_bucket = "simple"
|
28
|
+
# 是否使用内部连接,true - 使用 Aliyun 主机内部局域网的方式访问 false - 外部网络访问
|
29
|
+
config.aliyun_internal = true
|
30
|
+
# 配置存储的地区数据中心,默认: cn-hangzhou
|
31
|
+
# config.aliyun_area = "cn-hangzhou"
|
32
|
+
# 使用自定义域名,设定此项,carrierwave 返回的 URL 将会用自定义域名
|
33
|
+
# 自定于域名请 CNAME 到 you_bucket_name.oss.aliyuncs.com (you_bucket_name 是你的 bucket 的名称)
|
34
|
+
config.aliyun_host = "http://foo.bar.com"
|
35
|
+
# Bucket 为私有读取请设置 true,默认 false,以便得到的 URL 是能带有 private 空间访问权限的逻辑
|
36
|
+
# config.aliyun_private_read = false
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
## 跳过 CarrierWave 直接调用 Aliyun API
|
41
|
+
|
42
|
+
如果你有需求想跳过 CarrierWave,直接调用 Aliyun 的接口,可以参看 `spec/aliyun_spec.rb` 里面有例子。
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require File.expand_path('lib/carrierwave/aliyun/version')
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "carrierwave-aliyun-oss"
|
7
|
+
s.version = CarrierWave::Aliyun::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Jason Lee"]
|
10
|
+
s.email = ["huacnlee@gmail.com"]
|
11
|
+
s.homepage = "https://github.com/huacnlee/carrierwave-aliyun"
|
12
|
+
s.summary = %q{Aliyun OSS support for Carrierwave}
|
13
|
+
s.description = %q{Aliyun OSS support for Carrierwave}
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.license = 'MIT'
|
19
|
+
|
20
|
+
s.add_dependency "carrierwave", [">= 0.5.7"]
|
21
|
+
s.add_dependency "aliyun-sdk", [">= 0.4.0"]
|
22
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'carrierwave/storage/aliyun'
|
2
|
+
require 'carrierwave/aliyun/configuration'
|
3
|
+
|
4
|
+
CarrierWave.configure do |config|
|
5
|
+
config.storage_engines.merge!({ aliyun: 'CarrierWave::Storage::Aliyun' })
|
6
|
+
end
|
7
|
+
CarrierWave::Uploader::Base.send(:include, CarrierWave::Aliyun::Configuration)
|
8
|
+
|
9
|
+
if CarrierWave::VERSION <= '0.11.0'
|
10
|
+
require 'carrierwave/processing/mime_types'
|
11
|
+
CarrierWave::Uploader::Base.send(:include, CarrierWave::MimeTypes)
|
12
|
+
CarrierWave::Uploader::Base.send(:process, :set_content_type)
|
13
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module CarrierWave
|
2
|
+
module Aliyun
|
3
|
+
module Configuration
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
add_config :aliyun_access_id
|
8
|
+
add_config :aliyun_access_key
|
9
|
+
add_config :aliyun_bucket
|
10
|
+
add_config :aliyun_area
|
11
|
+
add_config :aliyun_internal
|
12
|
+
add_config :aliyun_host
|
13
|
+
add_config :aliyun_private_read
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
def add_config(name)
|
19
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
20
|
+
def self.#{name}(value=nil)
|
21
|
+
@#{name} = value if value
|
22
|
+
return @#{name} if self.object_id == #{self.object_id} || defined?(@#{name})
|
23
|
+
name = superclass.#{name}
|
24
|
+
return nil if name.nil? && !instance_variable_defined?("@#{name}")
|
25
|
+
@#{name} = name && !name.is_a?(Module) && !name.is_a?(Symbol) && !name.is_a?(Numeric) && !name.is_a?(TrueClass) && !name.is_a?(FalseClass) ? name.dup : name
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.#{name}=(value)
|
29
|
+
@#{name} = value
|
30
|
+
end
|
31
|
+
|
32
|
+
def #{name}
|
33
|
+
value = self.class.#{name}
|
34
|
+
value.instance_of?(Proc) ? value.call : value
|
35
|
+
end
|
36
|
+
RUBY
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,227 @@
|
|
1
|
+
require 'aliyun/oss'
|
2
|
+
require 'carrierwave'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module CarrierWave
|
6
|
+
module Storage
|
7
|
+
class Aliyun < Abstract
|
8
|
+
class Connection
|
9
|
+
PATH_PREFIX = %r{^/}
|
10
|
+
|
11
|
+
def initialize(uploader)
|
12
|
+
@uploader = uploader
|
13
|
+
@aliyun_access_id = uploader.aliyun_access_id
|
14
|
+
@aliyun_access_key = uploader.aliyun_access_key
|
15
|
+
@aliyun_bucket = uploader.aliyun_bucket
|
16
|
+
@aliyun_area = uploader.aliyun_area || 'cn-hangzhou'
|
17
|
+
@aliyun_private_read = uploader.aliyun_private_read
|
18
|
+
|
19
|
+
# Host for get request
|
20
|
+
@aliyun_host = uploader.aliyun_host || "http://#{@aliyun_bucket}.oss-#{@aliyun_area}.aliyuncs.com"
|
21
|
+
|
22
|
+
unless @aliyun_host.include?('//')
|
23
|
+
fail "config.aliyun_host requirement include // http:// or https://, but you give: #{@aliyun_host}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# 上传文件
|
28
|
+
# params:
|
29
|
+
# - path - remote 存储路径
|
30
|
+
# - file - CarrierWave::SanitizedFile
|
31
|
+
# - options:
|
32
|
+
# - content_type - 上传文件的 MimeType,默认 `image/jpg`
|
33
|
+
# returns:
|
34
|
+
# 图片的下载地址
|
35
|
+
def put(path, file, options = {})
|
36
|
+
path.sub!(PATH_PREFIX, '')
|
37
|
+
opts = {
|
38
|
+
content_type: options[:content_type] || 'image/jpg',
|
39
|
+
file: file.path
|
40
|
+
}
|
41
|
+
private_client.put_object(path, opts)
|
42
|
+
path_to_url(path)
|
43
|
+
end
|
44
|
+
|
45
|
+
# 读取文件
|
46
|
+
# params:
|
47
|
+
# - path - remote 存储路径
|
48
|
+
# returns:
|
49
|
+
# file data
|
50
|
+
def get(path)
|
51
|
+
path.sub!(PATH_PREFIX, '')
|
52
|
+
private_client.get_object(path){ |content| content }
|
53
|
+
end
|
54
|
+
|
55
|
+
# 删除 Remote 的文件
|
56
|
+
#
|
57
|
+
# params:
|
58
|
+
# - path - remote 存储路径
|
59
|
+
#
|
60
|
+
# returns:
|
61
|
+
# 图片的下载地址
|
62
|
+
def delete(path)
|
63
|
+
path.sub!(PATH_PREFIX, '')
|
64
|
+
private_client.delete_object(path)
|
65
|
+
path_to_url(path)
|
66
|
+
end
|
67
|
+
|
68
|
+
##
|
69
|
+
# 根据配置返回完整的上传文件的访问地址
|
70
|
+
def path_to_url(path)
|
71
|
+
[@aliyun_host, path].join('/')
|
72
|
+
end
|
73
|
+
|
74
|
+
# 私有空间访问地址,会带上实时算出的 token 信息
|
75
|
+
# 有效期 3600s
|
76
|
+
def private_get_url(path)
|
77
|
+
path.sub!(PATH_PREFIX, '')
|
78
|
+
public_client.object_url(path, true, 3600)
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def public_client
|
84
|
+
if defined?(@_public_client)
|
85
|
+
@_public_client
|
86
|
+
else
|
87
|
+
@_public_client = oss_client(false)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def private_client
|
92
|
+
if !@uploader.aliyun_internal
|
93
|
+
public_client
|
94
|
+
elsif defined?(@_private_client)
|
95
|
+
@_private_client
|
96
|
+
else
|
97
|
+
@_private_client = oss_client(true)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def oss_client(is_internal = false)
|
102
|
+
client = ::Aliyun::OSS::Client.new(
|
103
|
+
endpoint: (is_internal ? "oss-#{@aliyun_area}-internal.aliyuncs.com" : "oss-#{@aliyun_area}.aliyuncs.com"),
|
104
|
+
access_key_id: @aliyun_access_id,
|
105
|
+
access_key_secret: @aliyun_access_key
|
106
|
+
)
|
107
|
+
client.get_bucket(@aliyun_bucket)
|
108
|
+
end
|
109
|
+
|
110
|
+
# def oss_client
|
111
|
+
# return @oss_client if defined?(@oss_client)
|
112
|
+
# opts = {
|
113
|
+
# host: "oss-#{@aliyun_area}.aliyuncs.com",
|
114
|
+
# bucket: @aliyun_bucket
|
115
|
+
# }
|
116
|
+
# @oss_client = ::Aliyun::Oss::Client.new(@aliyun_access_id, @aliyun_access_key, opts)
|
117
|
+
# end
|
118
|
+
|
119
|
+
# def oss_upload_client
|
120
|
+
# return @oss_upload_client if defined?(@oss_upload_client)
|
121
|
+
|
122
|
+
# if @uploader.aliyun_internal
|
123
|
+
# host = "oss-#{@aliyun_area}-internal.aliyuncs.com"
|
124
|
+
# else
|
125
|
+
# host = "oss-#{@aliyun_area}.aliyuncs.com"
|
126
|
+
# end
|
127
|
+
|
128
|
+
# opts = {
|
129
|
+
# host: host,
|
130
|
+
# bucket: @aliyun_bucket
|
131
|
+
# }
|
132
|
+
|
133
|
+
# @oss_upload_client = ::Aliyun::Oss::Client.new(@aliyun_access_id, @aliyun_access_key, opts)
|
134
|
+
# end
|
135
|
+
end
|
136
|
+
|
137
|
+
class File < CarrierWave::SanitizedFile
|
138
|
+
##
|
139
|
+
# Returns the current path/filename of the file on Cloud Files.
|
140
|
+
#
|
141
|
+
# === Returns
|
142
|
+
#
|
143
|
+
# [String] A path
|
144
|
+
#
|
145
|
+
attr_reader :path
|
146
|
+
|
147
|
+
def initialize(uploader, base, path)
|
148
|
+
@uploader = uploader
|
149
|
+
@path = URI.encode(path)
|
150
|
+
@base = base
|
151
|
+
end
|
152
|
+
|
153
|
+
##
|
154
|
+
# Reads the contents of the file from Cloud Files
|
155
|
+
#
|
156
|
+
# === Returns
|
157
|
+
#
|
158
|
+
# [String] contents of the file
|
159
|
+
#
|
160
|
+
def read
|
161
|
+
object = oss_connection.get(@path)
|
162
|
+
@headers = object.headers
|
163
|
+
object.body
|
164
|
+
end
|
165
|
+
|
166
|
+
##
|
167
|
+
# Remove the file from Cloud Files
|
168
|
+
#
|
169
|
+
def delete
|
170
|
+
oss_connection.delete(@path)
|
171
|
+
true
|
172
|
+
rescue => e
|
173
|
+
# If the file's not there, don't panic
|
174
|
+
puts "carrierwave-aliyun delete file failed: #{e}"
|
175
|
+
nil
|
176
|
+
end
|
177
|
+
|
178
|
+
def url
|
179
|
+
if @uploader.aliyun_private_read
|
180
|
+
oss_connection.private_get_url(@path)
|
181
|
+
else
|
182
|
+
oss_connection.path_to_url(@path)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def content_type
|
187
|
+
headers[:content_type]
|
188
|
+
end
|
189
|
+
|
190
|
+
def content_type=(new_content_type)
|
191
|
+
headers[:content_type] = new_content_type
|
192
|
+
end
|
193
|
+
|
194
|
+
def store(file, opts = {})
|
195
|
+
oss_connection.put(@path, file, opts)
|
196
|
+
end
|
197
|
+
|
198
|
+
private
|
199
|
+
|
200
|
+
def headers
|
201
|
+
@headers ||= {}
|
202
|
+
end
|
203
|
+
|
204
|
+
def connection
|
205
|
+
@base.connection
|
206
|
+
end
|
207
|
+
|
208
|
+
def oss_connection
|
209
|
+
return @oss_connection if defined? @oss_connection
|
210
|
+
|
211
|
+
@oss_connection = CarrierWave::Storage::Aliyun::Connection.new(@uploader)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
# file: CarrierWave::SanitizedFile
|
216
|
+
def store!(file)
|
217
|
+
f = CarrierWave::Storage::Aliyun::File.new(uploader, self, uploader.store_path)
|
218
|
+
f.store(file, content_type: file.content_type)
|
219
|
+
f
|
220
|
+
end
|
221
|
+
|
222
|
+
def retrieve!(identifier)
|
223
|
+
CarrierWave::Storage::Aliyun::File.new(uploader, self, uploader.store_path(identifier))
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
data/spec/aliyun_spec.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
require "open-uri"
|
3
|
+
require "net/http"
|
4
|
+
|
5
|
+
describe "Aliyun" do
|
6
|
+
before(:all) do
|
7
|
+
@opts = {
|
8
|
+
:aliyun_access_id => ALIYUN_ACCESS_ID,
|
9
|
+
:aliyun_access_key => ALIYUN_ACCESS_KEY,
|
10
|
+
:aliyun_bucket => ALIYUN_BUCKET,
|
11
|
+
:aliyun_area => "cn-hangzhou",
|
12
|
+
:aliyun_internal => true,
|
13
|
+
:aliyun_host => "http://bison-dev.cn-hangzhou.oss.aliyun-inc.com"
|
14
|
+
}
|
15
|
+
|
16
|
+
@uploader = CarrierWave::Uploader::Base.new
|
17
|
+
@connection = CarrierWave::Storage::Aliyun::Connection.new(@uploader)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should put" do
|
21
|
+
url = @connection.put("a/a.jpg",load_file("foo.jpg"))
|
22
|
+
res = Net::HTTP.get_response(URI.parse(url))
|
23
|
+
expect(res.code).to eq "200"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should put with / prefix" do
|
27
|
+
url = @connection.put("/a/a.jpg",load_file("foo.jpg"))
|
28
|
+
res = Net::HTTP.get_response(URI.parse(url))
|
29
|
+
expect(res.code).to eq "200"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should delete" do
|
33
|
+
url = @connection.delete("/a/a.jpg")
|
34
|
+
res = Net::HTTP.get_response(URI.parse(url))
|
35
|
+
expect(res.code).to eq "404"
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should support custom domain" do
|
39
|
+
@uploader.aliyun_host = "https://foo.bar.com"
|
40
|
+
@connection = CarrierWave::Storage::Aliyun::Connection.new(@uploader)
|
41
|
+
url = @connection.put("a/a.jpg",load_file("foo.jpg"))
|
42
|
+
expect(url).to eq "https://foo.bar.com/a/a.jpg"
|
43
|
+
@uploader.aliyun_host = "http://foo.bar.com"
|
44
|
+
@connection = CarrierWave::Storage::Aliyun::Connection.new(@uploader)
|
45
|
+
url = @connection.put("a/a.jpg",load_file("foo.jpg"))
|
46
|
+
expect(url).to eq "http://foo.bar.com/a/a.jpg"
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'private read bucket' do
|
50
|
+
before do
|
51
|
+
@uploader.aliyun_private_read = true
|
52
|
+
@connection = CarrierWave::Storage::Aliyun::Connection.new(@uploader)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should get url include token' do
|
56
|
+
url = @connection.private_get_url('foobar.jpg')
|
57
|
+
# http://oss-cn-beijing.aliyuncs.com.//carrierwave-aliyun-test.oss-cn-beijing.aliyuncs.com/bar/foo.jpg?OSSAccessKeyId=1OpWEtPTjIDv5u8q&Expires=1455172009&Signature=4ibgQpfHOjVpqxG6162S8Ar3c6c=
|
58
|
+
expect(url).to include(*%w(Signature Expires OSSAccessKeyId))
|
59
|
+
expect(url).to include "http://#{@uploader.aliyun_bucket}.oss-#{@uploader.aliyun_area}.aliyuncs.com/foobar.jpg"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'File' do
|
64
|
+
it 'should have respond_to identifier' do
|
65
|
+
f = CarrierWave::Storage::Aliyun::File.new(@uploader, '', '')
|
66
|
+
expect(f).to respond_to(:identifier)
|
67
|
+
expect(f).to respond_to(:filename)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/spec/foo.gif
ADDED
Binary file
|
data/spec/foo.jpg
ADDED
Binary file
|
data/spec/foo.zip
ADDED
Binary file
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rspec'
|
3
|
+
require 'rails'
|
4
|
+
require 'active_record'
|
5
|
+
require "carrierwave"
|
6
|
+
require 'carrierwave/orm/activerecord'
|
7
|
+
require 'carrierwave/processing/mini_magick'
|
8
|
+
|
9
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
10
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
11
|
+
|
12
|
+
require "carrierwave-aliyun"
|
13
|
+
|
14
|
+
|
15
|
+
module Rails
|
16
|
+
class <<self
|
17
|
+
def root
|
18
|
+
[File.expand_path(__FILE__).split('/')[0..-3].join('/'),"spec"].join("/")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
ActiveRecord::Migration.verbose = false
|
24
|
+
ActiveRecord::Base.raise_in_transactional_callbacks = true
|
25
|
+
|
26
|
+
# 测试的时候需要修改这个地方
|
27
|
+
ALIYUN_ACCESS_ID = ENV['ALIYUN_ACCESS_ID'] || ''
|
28
|
+
ALIYUN_ACCESS_KEY = ENV['ALIYUN_ACCESS_KEY'] || ''
|
29
|
+
ALIYUN_BUCKET = ENV['ALIYUN_BUCKET'] || 'carrierwave-aliyun-test'
|
30
|
+
ALIYUN_AREA = ENV['ALIYUN_AREA'] || 'cn-beijing'
|
31
|
+
|
32
|
+
CarrierWave.configure do |config|
|
33
|
+
config.storage = :aliyun
|
34
|
+
config.aliyun_access_id = ALIYUN_ACCESS_ID
|
35
|
+
config.aliyun_access_key = ALIYUN_ACCESS_KEY
|
36
|
+
config.aliyun_bucket = ALIYUN_BUCKET
|
37
|
+
config.aliyun_area = ALIYUN_AREA
|
38
|
+
config.aliyun_internal = false
|
39
|
+
end
|
40
|
+
|
41
|
+
def load_file(fname)
|
42
|
+
File.open([Rails.root,fname].join("/"))
|
43
|
+
end
|
data/spec/upload_spec.rb
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
require "open-uri"
|
4
|
+
require "net/http"
|
5
|
+
ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
|
6
|
+
|
7
|
+
describe "Upload" do
|
8
|
+
def setup_db
|
9
|
+
ActiveRecord::Schema.define(:version => 1) do
|
10
|
+
create_table :photos do |t|
|
11
|
+
t.column :image, :string
|
12
|
+
t.column :content_type, :string
|
13
|
+
end
|
14
|
+
|
15
|
+
create_table :attachments do |t|
|
16
|
+
t.column :file, :string
|
17
|
+
t.column :content_type, :string
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def drop_db
|
23
|
+
ActiveRecord::Base.connection.tables.each do |table|
|
24
|
+
ActiveRecord::Base.connection.drop_table(table)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class PhotoUploader < CarrierWave::Uploader::Base
|
29
|
+
include CarrierWave::MiniMagick
|
30
|
+
|
31
|
+
version :small do
|
32
|
+
process :resize_to_fill => [120, 120]
|
33
|
+
end
|
34
|
+
|
35
|
+
def store_dir
|
36
|
+
"photos"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class AttachUploader < CarrierWave::Uploader::Base
|
41
|
+
include CarrierWave::MiniMagick
|
42
|
+
|
43
|
+
def store_dir
|
44
|
+
"attachs"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class Photo < ActiveRecord::Base
|
49
|
+
mount_uploader :image, PhotoUploader
|
50
|
+
end
|
51
|
+
|
52
|
+
class Attachment < ActiveRecord::Base
|
53
|
+
mount_uploader :file, AttachUploader
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
before :all do
|
58
|
+
setup_db
|
59
|
+
end
|
60
|
+
|
61
|
+
after :all do
|
62
|
+
drop_db
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "Upload Image" do
|
66
|
+
context "should upload image" do
|
67
|
+
before(:all) do
|
68
|
+
@file = load_file("foo.jpg")
|
69
|
+
@file1 = load_file("foo.gif")
|
70
|
+
@photo = Photo.new(:image => @file)
|
71
|
+
@photo1 = Photo.new(:image => @file1)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should upload file" do
|
75
|
+
expect(@photo.save).to eq true
|
76
|
+
expect(@photo1.save).to eq true
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should get uploaded file" do
|
80
|
+
img = open(@photo.image.url)
|
81
|
+
expect(img.size).to eq @file.size
|
82
|
+
expect(img.content_type).to eq 'image/jpeg'
|
83
|
+
img1 = open(@photo1.image.url)
|
84
|
+
expect(img1.size).to eq @file1.size
|
85
|
+
expect(img1.content_type).to eq 'image/gif'
|
86
|
+
end
|
87
|
+
|
88
|
+
it "sholud get small version uploaded file" do
|
89
|
+
expect(open(@photo.image.small.url)).not_to eq nil
|
90
|
+
expect(open(@photo1.image.small.url)).not_to eq nil
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context "should update zip" do
|
95
|
+
before(:all) do
|
96
|
+
@file = load_file("foo.zip")
|
97
|
+
@attachment = Attachment.new(:file => @file)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should upload file" do
|
101
|
+
expect(@attachment.save).to eq true
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should get uploaded file" do
|
105
|
+
attach = open(@attachment.file.url)
|
106
|
+
expect(attach.size).to eq @file.size
|
107
|
+
expect(attach.content_type).to eq 'application/zip'
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should delete old file when upload a new file again" do
|
111
|
+
old_url = @attachment.file.url
|
112
|
+
@attachment.file = load_file("foo.gif")
|
113
|
+
@attachment.save
|
114
|
+
res = Net::HTTP.get_response(URI.parse(old_url))
|
115
|
+
expect(res.code).to eq "404"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
metadata
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: carrierwave-aliyun-oss
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jason Lee
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-06-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: carrierwave
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.5.7
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.5.7
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: aliyun-sdk
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.4.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.4.0
|
41
|
+
description: Aliyun OSS support for Carrierwave
|
42
|
+
email:
|
43
|
+
- huacnlee@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- ".gitignore"
|
49
|
+
- ".rspec"
|
50
|
+
- ".travis.yml"
|
51
|
+
- CHANGELOG.md
|
52
|
+
- Gemfile
|
53
|
+
- Gemfile.lock
|
54
|
+
- README.md
|
55
|
+
- Rakefile
|
56
|
+
- carrierwave-aliyun.gemspec
|
57
|
+
- lib/carrierwave-aliyun.rb
|
58
|
+
- lib/carrierwave/aliyun/configuration.rb
|
59
|
+
- lib/carrierwave/aliyun/version.rb
|
60
|
+
- lib/carrierwave/storage/aliyun.rb
|
61
|
+
- spec/aliyun_spec.rb
|
62
|
+
- spec/foo.gif
|
63
|
+
- spec/foo.jpg
|
64
|
+
- spec/foo.zip
|
65
|
+
- spec/spec_helper.rb
|
66
|
+
- spec/upload_spec.rb
|
67
|
+
homepage: https://github.com/huacnlee/carrierwave-aliyun
|
68
|
+
licenses:
|
69
|
+
- MIT
|
70
|
+
metadata: {}
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options: []
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
requirements: []
|
86
|
+
rubyforge_project:
|
87
|
+
rubygems_version: 2.4.8
|
88
|
+
signing_key:
|
89
|
+
specification_version: 4
|
90
|
+
summary: Aliyun OSS support for Carrierwave
|
91
|
+
test_files:
|
92
|
+
- spec/aliyun_spec.rb
|
93
|
+
- spec/foo.gif
|
94
|
+
- spec/foo.jpg
|
95
|
+
- spec/foo.zip
|
96
|
+
- spec/spec_helper.rb
|
97
|
+
- spec/upload_spec.rb
|