qcloud_cos 0.3.0 → 0.4.0.pre

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
  SHA1:
3
- metadata.gz: c46f40136350e35780ce86e5a216af26a75ec799
4
- data.tar.gz: a90fe51412a6a35a83188e8509d7f51d48b469ec
3
+ metadata.gz: 75ee730d319d95b7fca2482722203b7e326c03a0
4
+ data.tar.gz: 7d3f04b960205007488d35688c8cf40146c1e3e2
5
5
  SHA512:
6
- metadata.gz: 9d889e680582184954f7bb93260762f9406acf285b7c7bb70ff439992bda8157e8e8c19cecc7e16ee367f2786982861d4decc8fe110bf9e73dbf4d38c4af0f30
7
- data.tar.gz: ffd68ec5201c615ba2d12598a4595148214260a0a90f30d03c837b318768e0a5651be14e97197bcc2154854c8b298f05d4fb278c1ad416e6fa4e3068f7a91595
6
+ metadata.gz: 3103a965be5176a4a7cb0346b748e6642d2b35dbb3b6aa9d7fb69be1ece65c4ee9e5b5e0bb222260931afd7a043d8ee06d5e11205a232c14b42f56ed9280c988
7
+ data.tar.gz: 3f00b1d37848247ac3a12fe521a131c39f4f37612c9600aaf1c8212d0cffcfef7807aa86252addbac7144e71f9c6c817f0be598ef99572a580c92e6d6e017676
data/.gitignore CHANGED
@@ -7,3 +7,5 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ .qcloud_cos.yml
11
+ .ruby-version
data/README.md CHANGED
@@ -49,12 +49,12 @@ More Example and Scenario, visit our [Document](#document)
49
49
 
50
50
  Here is original Restful API, It has the most detailed and authoritative explanation for every API.
51
51
 
52
- + [COS RESTful API文档](http://www.qcloud.com/wiki/RESTful_API%E6%96%87%E6%A1%A3)
52
+ + [COS RESTful API文档](http://www.qcloud.com/wiki/RESTful_API%E6%96%87%E6%A1%A3)
53
53
  + [COS 详细文档](http://www.qcloud.com/doc/product/227/%E4%BA%A7%E5%93%81%E4%BB%8B%E7%BB%8D)
54
54
 
55
55
  Here is our RDoc Document, It's well format to help you find more detail about methods.
56
56
 
57
- + [RDoc Document](http://www.rubydoc.info/gems/qcloud_cos/0.1.0)
57
+ + [RDoc Document](http://www.rubydoc.info/gems/qcloud_cos/0.3.0)
58
58
 
59
59
 
60
60
  Here are some more guides for help you. Welcome to advice.
data/bin/console CHANGED
@@ -11,12 +11,12 @@ require 'qcloud_cos'
11
11
  # Pry.start
12
12
 
13
13
  QcloudCos.configure do |config|
14
- config.app_id = ENV['QCLOUD_APP_ID'] || 'app-id'
15
- config.secret_id = ENV['QCLOUD_SECRET_ID'] || 'secret_id'
16
- config.secret_key = ENV['QCLOUD_SECRET_KEY'] || 'secret_key'
17
- config.endpoint = ENV['QCLOUD_ENDPOINT'] || 'https://web.file.myqcloud.com/files/v1/'
18
- config.bucket = ENV['QCLOUD_BUCKET'] || 'privatesdkdemo'
19
- config.ssl_ca_file = ENV['SSL_CA_FILE'] || 'path/to/ssl/ca/file'
14
+ config.app_id = ENV['QCLOUD_COS_APP_ID'] || 'app-id'
15
+ config.secret_id = ENV['QCLOUD_COS_SECRET_ID'] || 'secret_id'
16
+ config.secret_key = ENV['QCLOUD_COS_SECRET_KEY'] || 'secret_key'
17
+ config.endpoint = ENV['QCLOUD_COS_ENDPOINT'] || 'http://web.file.myqcloud.com/files/v1/'
18
+ config.bucket = ENV['QCLOUD_COS_BUCKET'] || 'privatesdkdemo'
19
+ config.ssl_ca_file = ENV['QCLOUD_COS_SSL_CA_FILE'] || 'path/to/ssl/ca/file'
20
20
  end
21
21
 
22
22
  require 'irb'
data/bin/qcloud-cos ADDED
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env ruby
2
+ require 'bundler/setup'
3
+ require 'commander/import'
4
+ require 'qcloud_cos/cli'
5
+ require 'awesome_print'
6
+
7
+ program :name, 'qcloud-cos'
8
+ program :version, QcloudCos::VERSION
9
+ program :description, 'command-line tool for Qcloud COS'
10
+ program :help, 'Author', 'Newell Zhu<zlx.star@gmail.com>'
11
+ default_command :help
12
+
13
+ command :config do |c|
14
+ c.syntax = 'qcloud-cos config'
15
+ c.description = 'Init config, eg: qcloud-cos config'
16
+ c.action do |args, options|
17
+ QcloudCos::Cli.config
18
+ end
19
+ end
20
+
21
+ command :info do |c|
22
+ c.syntax = 'qcloud-cos info [options] [dest_path]'
23
+ c.description = 'Obtain information'
24
+ c.example 'Obtain bucket information', '$ qcloud-cos info'
25
+ c.example 'Obtain information for /test/', '$ qcloud-cos info /test/'
26
+ c.example 'Obtain information for /production.log', '$ qcloud-cos info /production.log'
27
+ c.example 'Obtain information for /production.log from bucket2', '$ qcloud-cos info --bucket bucket2 /production.log'
28
+ c.option '--bucket Bucket Name', String, 'specify bucket name, it will override default bucket'
29
+ c.action do |args, options|
30
+ abort unless QcloudCos::Cli.environment_configed?
31
+ begin
32
+ cli = QcloudCos::Cli.init
33
+ ap cli.info(args, options), indent: -2
34
+ rescue => e
35
+ say_error e.message
36
+ end
37
+ end
38
+ end
39
+
40
+ command :list do |c|
41
+ c.syntax = 'qcloud-cos list [options] [dest_path]'
42
+ c.description = 'List objects under [dest_path]'
43
+ c.example 'List all objects under /', '$ qcloud-cos list'
44
+ c.example 'List all objects under /test/', '$ qcloud-cos list /test/'
45
+ c.example 'List first 10 objects under /test/', '$ qcloud-cos list --num 10 /test/'
46
+ c.example 'List all objects under / for bucket: bucket2', '$ qcloud-cos list --num 10 --bucket bucket2 /test/'
47
+ c.option '--bucket Bucket Name', String, 'specify bucket name, it will override default bucket'
48
+ c.option '--num Num', Integer, 'specify max objects, default is 100'
49
+ c.action do |args, options|
50
+ abort unless QcloudCos::Cli.environment_configed?
51
+ begin
52
+ cli = QcloudCos::Cli.init
53
+ cli.list(args, options).map{|path| puts path }
54
+ rescue => e
55
+ say_error e.message
56
+ end
57
+ end
58
+ end
59
+
60
+ command :upload do |c|
61
+ c.syntax = 'qcloud-cos upload [options] file [dest_path]'
62
+ c.description = 'Upload file or folder to COS'
63
+ c.example 'Upload production.log to /', '$ qcloud-cos upload production.log'
64
+ c.example 'Upload production.log to /data/', '$ qcloud-cos upload production.log /data/'
65
+ c.example 'Upload all files under ./test/ to /data/', '$ qcloud-cos upload test/ /data/'
66
+ c.example 'Upload all files under ./test/ to /data/ with other bucket: bucket2', '$ qcloud-cos upload --bucket bucket2 test/ /data/'
67
+ c.example 'Upload production.log to /data/ with slice_size and min', '$ qcloud-cos upload --size 10 --min 100 production.log /data/'
68
+ c.option '--bucket Bucket Name', String, 'specify bucket name, it will override default bucket'
69
+ c.option '--size Slice Size', Integer, "specify slice size for slice upload in Bytes, default: #{QcloudCos::DEFAULT_SLICE_SIZE}(#{QcloudCos::DEFAULT_SLICE_SIZE/1024/1024}M)"
70
+ c.option '--min Min Slice File Size', Integer, "specify min slice file size in Bytes, default: default: #{QcloudCos::MIN_SLICE_FILE_SIZE * 1024 * 1024}(#{QcloudCos::MIN_SLICE_FILE_SIZE}M)"
71
+ c.action do |args, options|
72
+ abort unless QcloudCos::Cli.environment_configed?
73
+ begin
74
+ cli = QcloudCos::Cli.init
75
+ cli.upload(args, options)
76
+ rescue => e
77
+ Commander::UI.say_error e.message
78
+ end
79
+ end
80
+ end
81
+
82
+ command :download do |c|
83
+ c.syntax = 'qcloud-cos download [options] dest_path [save_path]'
84
+ c.description = 'Download objects from COS'
85
+ c.example 'Download file from /data/production.log and save current path', '$ qcloud-cos download /data/production.log'
86
+ c.example 'Download file from /data/production.log and save under ./data/', '$ qcloud-cos download /data/production.log ./data'
87
+ c.example 'Download whole folder /data/test/ and save under ./data/', '$ qcloud-cos download /data/test/ ./data'
88
+ c.example 'Download whole folder /data/test/ from bucket2 and save under ./data/', '$ qcloud-cos download --bucket bucket2 /data/test/ ./data'
89
+ c.option '--bucket Bucket Name', String, 'specify bucket name, it will override default bucket'
90
+ c.action do |args, options|
91
+ abort unless QcloudCos::Cli.environment_configed?
92
+ begin
93
+ cli = QcloudCos::Cli.init
94
+ cli.download(args, options)
95
+ rescue => e
96
+ Commander::UI.say_error e.message
97
+ end
98
+ end
99
+ end
100
+
101
+ command :remove do |c|
102
+ c.syntax = 'qcloud-cos remove [options] dest_path'
103
+ c.description = 'Remove objects from COS'
104
+ c.example 'Remove file /data/production.log', '$ qcloud-cos remove /data/production.log'
105
+ c.example 'Remove folder /data/test/', '$ qcloud-cos remove /data/test/'
106
+ c.example 'Remove folder /data/test/ in recursive', '$ qcloud-cos remove --recursive /data/test/'
107
+ c.example 'Remove folder /data/test/ from bucket2', '$ qcloud-cos download --bucket bucket2 /data/test/'
108
+ c.option '--bucket Bucket Name', String, 'specify bucket name, it will override default bucket'
109
+ c.option '--[no-]recursive', 'specify recursive or not when remove folder'
110
+ c.action do |args, options|
111
+ abort unless QcloudCos::Cli.environment_configed?
112
+ begin
113
+ cli = QcloudCos::Cli.init
114
+ cli.remove(args, options)
115
+ Commander::UI.say_ok 'OK'
116
+ rescue => e
117
+ Commander::UI.say_error e.message
118
+ end
119
+ end
120
+ end
data/lib/qcloud_cos.rb CHANGED
@@ -11,6 +11,8 @@ module QcloudCos
11
11
  DEFAULT_SLICE_SIZE = 3_145_728 # 3M
12
12
  MIN_SLICE_FILE_SIZE = 10 # 10M
13
13
  MAX_RETRY_TIMES = 3
14
+ QCLOUD_COS_CONFIG = '.qcloud-cos.yml'
15
+ DEFAULT_ENDPOINT = 'http://web.file.myqcloud.com/files/v1/'
14
16
 
15
17
  class << self
16
18
  include Api
@@ -38,12 +40,10 @@ module QcloudCos
38
40
 
39
41
  def validates(path, options, path_validate = :file_only)
40
42
  Utils.stringify_keys!(options)
41
- file_validates(path, path_validate)
42
-
43
- bucket = options['bucket'] || config.bucket
44
- fail MissingBucketError unless bucket
45
43
 
46
- bucket
44
+ file_validates(path, path_validate)
45
+ num_validates(options['num'].to_i) if options['num']
46
+ bucket_validates(options['bucket'])
47
47
  end
48
48
 
49
49
  def fixed_path(path)
@@ -62,5 +62,15 @@ module QcloudCos
62
62
  FolderObject.validate(path)
63
63
  end
64
64
  end
65
+
66
+ def num_validates(number)
67
+ fail InvalidNumError if (number > 199 || number < 1)
68
+ end
69
+
70
+ def bucket_validates(bucket_name)
71
+ bucket = bucket_name || config.bucket
72
+ fail MissingBucketError unless bucket
73
+ bucket
74
+ end
65
75
  end
66
76
  end
@@ -9,7 +9,7 @@ module QcloudCos
9
9
  # @param path [String] 指定目标路径, 以 / 结尾, 则列出该目录下文件或者文件夹,不以 / 结尾,就搜索该前缀的文件或者文件夹
10
10
  # @param options [Hash] 额外参数
11
11
  # @option options [String] :bucket (config.bucket_name) 指定当前 bucket, 默认是配置里面的 bucket
12
- # @option options [Integer] :num (100) 指定需要拉取的条目
12
+ # @option options [Integer] :num (100) 指定需要拉取的条目, 可选范围: 1~199
13
13
  # @option options [String] :pattern (eListBoth) 指定拉取的内容,可选值: eListBoth, eListDirOnly, eListFileOnly
14
14
  # @option options [Integer] :order (0) 指定拉取文件的顺序, 默认为正序(=0), 可选值: 0, 1
15
15
  # @option options [String] :context ("") 透传字段,查看第一页,则传空字符串。若需要翻页,需要将前一页返回值中的context透传到参数中。order用于指定翻页顺序。若order填0,则从当前页正序/往下翻页;若order填1,则从当前页倒序/往上翻页。
@@ -110,8 +110,15 @@ module QcloudCos
110
110
 
111
111
  # 分片上传
112
112
  #
113
+ # @example
114
+ #
115
+ # upload_slice('/data/test.log', 'test.log') do |pr|
116
+ # puts "uploaded #{pr * 100}%"
117
+ # end
118
+ #
113
119
  # @param dst_path [String] 指定文件的目标路径
114
120
  # @param src_path [String] 指定文件的本地路径
121
+ # @param block [Block] 指定 Block 来显示进度提示
115
122
  # @param options [Hash] options
116
123
  # @option options [String] :bucket (config.bucket_name) 指定当前 bucket, 默认是配置里面的 bucket
117
124
  # @option options [Integer] :biz_attr 指定文件的 biz_attr 由业务端维护, 会在文件信息中返回
@@ -123,7 +130,7 @@ module QcloudCos
123
130
  # @raise [InvalidFilePathError] 如果目标路径是非法文件路径
124
131
  #
125
132
  # @return [Hash]
126
- def upload_slice(dst_path, src_path, options = {})
133
+ def upload_slice(dst_path, src_path, options = {}, &block)
127
134
  dst_path = fixed_path(dst_path)
128
135
  fail FileNotExistError unless File.exist?(src_path)
129
136
  bucket = validates(dst_path, options)
@@ -133,7 +140,6 @@ module QcloudCos
133
140
  sign = authorization.sign(bucket)
134
141
 
135
142
  resp = init_slice_upload(dst_path, filesize, sha, options.merge('sign' => sign))
136
- puts "init slice upload: #{resp}"
137
143
 
138
144
  data = resp['data']
139
145
  return data if data.key?('url') # 妙传命中
@@ -150,7 +156,8 @@ module QcloudCos
150
156
  retry_times = 0
151
157
  begin
152
158
  result = upload_part(dst_path, session, offset, filecontent, options)
153
- puts "upload part data: #{result}"
159
+ progress = [offset + slice_size, filesize].min
160
+ yield((progress.to_f/filesize).round(2)) if block_given?
154
161
 
155
162
  if result.key?('data') && result['data'].key?('session')
156
163
  session = result['data']['session']
@@ -159,7 +166,6 @@ module QcloudCos
159
166
  end
160
167
  rescue => e
161
168
  retry_times += 1
162
- puts "retry part upload request with offset:#{offset}, slice_size:#{slice_size} ..."
163
169
  retry if retry_times <= config.max_retry_times
164
170
  raise e
165
171
  end
@@ -168,7 +174,6 @@ module QcloudCos
168
174
  end
169
175
 
170
176
  # 初始化分片上传
171
- # @private
172
177
  #
173
178
  # @param path [String] 指定上传文件的路径
174
179
  # @param filesize [Integer] 指定文件总大小
@@ -190,10 +195,8 @@ module QcloudCos
190
195
 
191
196
  http.post(url, query: query, headers: { 'Authorization' => sign }).parsed_response
192
197
  end
193
- private :init_slice_upload
194
198
 
195
199
  # 上传分片数据
196
- # @private
197
200
  #
198
201
  # @param path [String] 指定上传文件的路径
199
202
  # @param session [String] 指定分片上传的 session id
@@ -213,7 +216,6 @@ module QcloudCos
213
216
 
214
217
  http.post(url, query: query, headers: { 'Authorization' => sign }).parsed_response
215
218
  end
216
- private :upload_part
217
219
 
218
220
  # 更新文件或者目录信息
219
221
  #
@@ -0,0 +1,345 @@
1
+ # encoding: utf-8
2
+ require 'rubygems'
3
+ require 'commander'
4
+ require 'awesome_print'
5
+ require 'qcloud_cos'
6
+
7
+ module QcloudCos
8
+ class Cli
9
+ include Commander::Methods
10
+
11
+ QCLOUD_COS_ENV_MAPPING = {
12
+ app_id: 'QCLOUD_COS_APP_ID',
13
+ secret_id: 'QCLOUD_COS_SECRET_ID',
14
+ secret_key: 'QCLOUD_COS_SECRET_KEY',
15
+ endpoint: 'QCLOUD_COS_ENDPOINT',
16
+ bucket: 'QCLOUD_COS_BUCKET',
17
+ ssl_ca_file: 'QCLOUD_COS_SSL_CA_FILE',
18
+ max_retry_times: 'QCLOUD_COS_MAX_RETRY_TIMES'
19
+ }
20
+
21
+ # 交互模式配置环境
22
+ # 命令: $ qcloud-cos config
23
+ def self.config(config_path = nil)
24
+ config_path = config_path || QcloudCos::QCLOUD_COS_CONFIG
25
+ return Commander::UI.say_error("#{config_path} already exist, remove it first or direct edit it!") if File.exist?(config_path)
26
+
27
+ app_id = Commander::UI.ask 'Qcloud COS APP ID: '
28
+ return Commander::UI.say_error("Missing Qcloud COS APP ID") if app_id.empty?
29
+
30
+ secret_id = Commander::UI.ask 'Qcloud COS Secret ID: '
31
+ return Commander::UI.say_error("Missing Qcloud COS Secret ID") if secret_id.empty?
32
+
33
+ secret_key = Commander::UI.ask 'Qcloud COS Secret Key: '
34
+ return Commander::UI.say_error("Missing Qcloud COS Secret Key") if secret_key.empty?
35
+
36
+ endpoint = Commander::UI.ask "Default Qcloud COS Endpoint [#{QcloudCos::DEFAULT_ENDPOINT}]: "
37
+ endpoint = QcloudCos::DEFAULT_ENDPOINT if endpoint.empty?
38
+ bucket = Commander::UI.ask 'Default Qcloud COS Bucket: '
39
+
40
+ write_config(
41
+ config_path,
42
+ app_id: app_id,
43
+ secret_id: secret_id,
44
+ secret_key: secret_key,
45
+ endpoint: endpoint,
46
+ bucket: bucket
47
+ )
48
+ end
49
+
50
+ # 检查环境是否配置
51
+ #
52
+ # @return [Boolean]
53
+ def self.environment_configed?
54
+ configed = File.exist?(QcloudCos::QCLOUD_COS_CONFIG) || !ENV['QCLOUD_COS_APP_ID'].to_s.empty?
55
+ Commander::UI.say_error("Use `qcloud-cos config` first or export your environments") unless configed
56
+ configed
57
+ end
58
+
59
+ # 检查环境,初始化 Cli
60
+ def self.init
61
+ QcloudCos.configure do |config|
62
+ load_config.each { |k, v| config.send("#{k}=", v) }
63
+ end
64
+
65
+ self.new
66
+ end
67
+
68
+ # 查看信息
69
+ # 命令: $ qcloud-cos info [options] [dest_path]
70
+ #
71
+ # @example
72
+ # # 查看 Bucket 信息
73
+ # qcloud-cos info
74
+ #
75
+ # # 查看 /production.log 信息
76
+ # qcloud-cos info /production.log
77
+ #
78
+ # # 查看 /test/ 信息
79
+ # qcloud-cos info /test/
80
+ #
81
+ # # 查看 bucket2 上的 /production.log 信息
82
+ # qcloud-cos info --bucket bucket2 /production.log
83
+ def info(args, options)
84
+ path = args.shift || '/'
85
+ opts = parse(options)
86
+
87
+ QcloudCos.stat(path, opts)['data']
88
+ end
89
+
90
+ # 列出文件或者文件夹
91
+ # 使用: $ qcloud-cos list [options] [dest_path]
92
+ #
93
+ # @example
94
+ #
95
+ # # 列出 / 下面的所有对象
96
+ # qcloud-cos list
97
+ #
98
+ # # 列出 /test/ 下面的所有对象
99
+ # qcloud-cos list /test/
100
+ #
101
+ # # 列出 /test/ 下面的前 10 个对象
102
+ # qcloud-cos list --num 10 /test/
103
+ #
104
+ # # 列出 bucket2 的 /test/ 下面的所有对象
105
+ # qcloud-cos list --bucket bucket2 /test/
106
+ #
107
+ def list(args, options)
108
+ path = args.shift || '/'
109
+ opts = parse(options)
110
+ opts[:num] = options.num || 100
111
+
112
+ objects = QcloudCos.list(path, opts)
113
+ objects.map do |object|
114
+ File.join(path, object.is_a?(QcloudCos::FolderObject) ? "#{object.name}/" : object.name)
115
+ end
116
+ end
117
+
118
+ # 上传文件或者目录到 COS
119
+ # 命令: qcloud-cos upload [options] file [dest_path]
120
+ #
121
+ # @example
122
+ #
123
+ # # 把 production.log 上传到 /
124
+ # qcloud-cos upload production.log
125
+ #
126
+ # # 把 production.log 上传到 /data/ 下面
127
+ # qcloud-cos upload production.log /data/
128
+ #
129
+ # # 把 ./test/ 整个文件夹上传到 /data/ 下面
130
+ # qcloud-cos upload test/ /data/
131
+ #
132
+ # # 把 ./test/ 整个文件夹上传到 bucket2 的 /data/ 下面
133
+ # qcloud-cos upload --bucket bucket2 test/ /data/
134
+ def upload(args, options)
135
+ path = args.shift
136
+ return Commander::UI.say_error("file missing, see example: $ qcloud-cos upload -h") unless path
137
+ return Commander::UI.say_error("file #{path} not exist") unless File.exist?(path)
138
+
139
+ dest_path = args.shift || '/'
140
+ return Commander::UI.say_error("dest_path must end with /, see example: $ qcloud-cos upload -h") unless dest_path.end_with?('/')
141
+
142
+ opts = parse(options)
143
+ opts[:slice_size] = options.size || QcloudCos::DEFAULT_SLICE_SIZE
144
+ opts[:min] = options.min || QcloudCos::MIN_SLICE_FILE_SIZE * 1024 * 1024
145
+
146
+ if path.end_with?('/')
147
+ upload_folder(path, dest_path, opts)
148
+ else
149
+ upload_file(path, dest_path, opts)
150
+ end
151
+ end
152
+
153
+ # 下载文件或者目录
154
+ # 命令: $ qcloud-cos download [options] dest_path [save_path]
155
+ #
156
+ # @example
157
+ #
158
+ # # 把 /data/production.log 下载到当前目录
159
+ # qcloud-cos download /data/production.log
160
+ #
161
+ # # 把 /data/production.log 下载到 ./data/ 下
162
+ # qcloud-cos download /data/production.log ./data
163
+ #
164
+ # # 把 /data/test/ 整个目录下载并保存到 ./data/ 目录下面
165
+ # qcloud-cos download /data/test/ ./data
166
+ #
167
+ # # 把 bucket2 下的 /data/test/ 整个目录下载并保存到 ./data/ 下面
168
+ # qcloud-cos download --bucket bucket2 /data/test/ ./data
169
+ #
170
+ def download(args, options)
171
+ path = args.shift
172
+ return Commander::UI.say_error("missing path, see example: $ qcloud-cos download -h") unless path
173
+ opts = parse(options)
174
+ opts[:save_path] = args.shift || '.'
175
+
176
+ if path.end_with?('/')
177
+ download_folder(path, opts)
178
+ else
179
+ download_file(path, opts)
180
+ end
181
+ end
182
+
183
+ # 删除目录或者文件夹
184
+ # 命令: $ qcloud-cos remove [options] dest_path
185
+ #
186
+ # @example
187
+ #
188
+ # # 删除文件/data/production.log
189
+ # qcloud-cos remove /data/production.log
190
+ #
191
+ # # 删除目录 /data/test/, 目录非空会失败
192
+ # qcloud-cos remove /data/test/
193
+ #
194
+ # # 级联删除目录 /data/test/
195
+ # qcloud-cos remove --recursive /data/test/
196
+ #
197
+ # # 删除 bucket2 下面的目录 /data/test/
198
+ # qcloud-cos download --bucket bucket2 /data/test/
199
+ def remove(args, options)
200
+ path = args.shift
201
+ return Commander::UI.say_error("missing dest_path, see example: $ qcloud-cos remove -h") unless path
202
+
203
+ opts = parse(options)
204
+
205
+ if path.end_with?('/')
206
+ QcloudCos.delete_folder(path, opts.merge(recursive: !!options.recursive))
207
+ else
208
+ QcloudCos.delete_file(path, opts)
209
+ end
210
+ end
211
+
212
+ private
213
+
214
+ def upload_file(path, dest_path, opts)
215
+ dest_path = File.join(dest_path, path.split('/').last)
216
+ file = File.new(path)
217
+ if file.size > opts[:min]
218
+ QcloudCos.upload_slice(dest_path, path, Utils.hash_slice(opts, :bucket).merge(slice_size: opts[:slice_size]))
219
+ else
220
+ QcloudCos.upload(dest_path, file, Utils.hash_slice(opts, :bucket))
221
+ end
222
+ Commander::UI.say_ok "#{path} uploaded to #{dest_path}..."
223
+ rescue => e
224
+ Commander::UI.say_error "Failed when uploaded #{path} ===> #{e.message}"
225
+ ensure
226
+ file && file.close
227
+ end
228
+
229
+ def upload_folder(path, dest_path, opts)
230
+ file_path_map = {}
231
+ Dir.glob("#{path}**/*") do |file_path|
232
+ split_path = file_path.sub(path, '').split('/')
233
+ new_path =
234
+ if File.file?(file_path)
235
+ split_path.size > 1 ? File.join(dest_path, *split_path[0..-2]) : dest_path
236
+ else
237
+ file_path = File.join(file_path, '')
238
+ File.join(dest_path, *split_path, '')
239
+ end
240
+
241
+ file_path_map[file_path] = new_path
242
+ end
243
+ remove_subdirectories(file_path_map)
244
+
245
+ file_path_map.each do |file_path, dest_path|
246
+ if file_path.end_with?('/')
247
+ QcloudCos.create_folder(dest_path, opts)
248
+ Commander::UI.say_ok "Create folder #{dest_path}"
249
+ else
250
+ upload_file(file_path, dest_path, opts)
251
+ end
252
+ end
253
+ end
254
+
255
+ def download_file(path, opts)
256
+ save_path = opts.delete(:save_path)
257
+ FileUtils.mkdir_p(save_path) unless File.exist?(save_path)
258
+
259
+ file_path = File.join(save_path, path.split('/').last)
260
+ signed_access_url = opts[:access_url] ? opts.delete(:access_url) : QcloudCos.public_url(path, opts)
261
+ save_to_file(signed_access_url, file_path)
262
+ Commander::UI.say_ok("Save #{path} to #{file_path}")
263
+ rescue => e
264
+ Commander::UI.say_error("Failed when Download #{path} ===> #{e.message}")
265
+ end
266
+
267
+ def download_folder(path, opts)
268
+ save_path = opts.delete(:save_path)
269
+ loop do
270
+ objects = QcloudCos.list(path, opts)
271
+ objects.each do |object|
272
+ if object.is_a?(QcloudCos::FolderObject)
273
+ new_path = File.join(save_path, object.name)
274
+ unless File.exist?(new_path)
275
+ FileUtils.mkdir_p(new_path) unless File.exist?(new_path)
276
+ Commander::UI.say_ok "Save #{path}#{object.name}/ to #{new_path}/"
277
+ end
278
+ download_folder("#{path}#{object.name}/", opts.merge(save_path: new_path))
279
+ elsif object.is_a?(QcloudCos::FileObject)
280
+ if object.access_url
281
+ download_file("#{path}#{object.name}", opts.merge(save_path: save_path, access_url: object.access_url))
282
+ else
283
+ download_file("#{path}#{object.name}", opts.merge(save_path: save_path))
284
+ end
285
+ end
286
+ end
287
+ break unless objects.has_more
288
+ opts['context'] = objects.context
289
+ end
290
+ end
291
+
292
+ def self.load_config
293
+ file_config = load_file_config
294
+
295
+ config = {}
296
+ QCLOUD_COS_ENV_MAPPING.each do |key, env_name|
297
+ config[key] = ENV[env_name] || file_config[key.to_s]
298
+ end
299
+ config
300
+ end
301
+
302
+ def self.load_file_config
303
+ return {} unless File.exist?(QcloudCos::QCLOUD_COS_CONFIG)
304
+
305
+ Hash[File.open(QcloudCos::QCLOUD_COS_CONFIG).map do |line|
306
+ key, value = line.split('=')
307
+ value.chomp!.empty? ? nil : [key, value]
308
+ end.compact]
309
+ end
310
+
311
+ def parse(options)
312
+ opts = {}
313
+ opts[:bucket] = options.bucket if options.bucket
314
+ opts
315
+ end
316
+
317
+ def remove_subdirectories(path_map)
318
+ new_map = path_map.dup
319
+ new_map.each do |_, dest_path|
320
+ path_map.reject! do |file_path, dest|
321
+ file_path.end_with?('/') && dest_path.start_with?(dest)
322
+ end
323
+ end
324
+ end
325
+
326
+ def save_to_file(access_url, file_path)
327
+ File.open(file_path, "wb") do |f|
328
+ f.write HTTParty.get(access_url)
329
+ end
330
+ end
331
+
332
+ def self.write_config(config_path, options)
333
+ File.open(config_path, "w") do |file|
334
+ file.puts "app_id=#{options[:app_id]}"
335
+ file.puts "secret_id=#{options[:secret_id]}"
336
+ file.puts "secret_key=#{options[:secret_key]}"
337
+ file.puts "endpoint=#{options[:endpoint]}"
338
+ file.puts "bucket=#{options[:bucket]}"
339
+ file.puts "ssl_ca_file="
340
+ file.puts "max_retry_times="
341
+ end
342
+ end
343
+
344
+ end
345
+ end
@@ -5,5 +5,10 @@ module QcloudCos
5
5
  def max_retry_times
6
6
  @max_retry_times || MAX_RETRY_TIMES
7
7
  end
8
+
9
+ def max_retry_times=(times)
10
+ @max_retry_times = times.to_i
11
+ @max_retry_times = MAX_RETRY_TIMES if @max_retry_times.zero?
12
+ end
8
13
  end
9
14
  end
@@ -6,7 +6,8 @@ module QcloudCos
6
6
  # @param bucket_name [String] :bucket (config.bucket) 指定当前 bucket, 默认是配置里面的 bucket
7
7
  #
8
8
  # @return [Hash] 返回 Bucket 信息
9
- def bucket_info(bucket_name = config.bucket)
9
+ def bucket_info(bucket_name = nil)
10
+ bucket_name = bucket_name || config.bucket
10
11
  stat('/', bucket: bucket_name)['data']
11
12
  rescue
12
13
  {}
@@ -46,4 +46,10 @@ module QcloudCos
46
46
  super('分片上传不能缺少 Session ID')
47
47
  end
48
48
  end
49
+
50
+ class InvalidNumError < Error
51
+ def initialize
52
+ super('单次列取目录数量必须在1~199')
53
+ end
54
+ end
49
55
  end
@@ -1,3 +1,3 @@
1
1
  module QcloudCos
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.0.pre'
3
3
  end
data/qcloud_cos.gemspec CHANGED
@@ -14,13 +14,15 @@ Gem::Specification.new do |spec|
14
14
  spec.homepage = 'https://github.com/tencentyun'
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
- spec.bindir = 'exe'
18
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
17
+ spec.bindir = 'bin'
18
+ spec.executables = ['qcloud-cos']
19
19
  spec.require_paths = ['lib']
20
20
 
21
21
  spec.add_dependency 'httparty'
22
22
  spec.add_dependency 'httmultiparty'
23
23
  spec.add_dependency 'addressable'
24
+ spec.add_dependency 'commander'
25
+ spec.add_dependency 'awesome_print'
24
26
 
25
27
  spec.add_development_dependency 'bundler'
26
28
  spec.add_development_dependency 'rake'
data/wiki/get_started.md CHANGED
@@ -21,7 +21,7 @@
21
21
  10. [检查目录下是否有文件夹 (contains_folder?)](#判断目录是否为空)
22
22
  3. [文件操作](#文件操作)
23
23
  1. [上传文件 (create, upload)](#文件上传)
24
- 2. [分片上传文件,支持断点续传 (upload_slice)](#文件分片上传)
24
+ 2. [分片上传文件,支持断点续传 (upload_slice)](#大文件分片上传)
25
25
  3. [更新文件属性 (update)](#更新属性)
26
26
  4. [查询文件信息 (stat)](#目录或者文件查询)
27
27
  5. [列出文件 (list, list_files)](#列举目录下文件或目录)
@@ -30,8 +30,19 @@
30
30
  8. [文件搜索 (list)](#列举目录下文件或目录)
31
31
  9. [检查文件是否存在 (exists?, exist?)](#判断目录或者文件是否存在)
32
32
  10. [查看目录下文件数量 (count)](#查看文件和文件夹数目)
33
- 11. [检查目录下是否有文件 (contains_folder?)](#判断目录是否为空)
34
- 3. [其它资源](#其它资源)
33
+ 11. [检查目录下是否有文件 (contains_folder?)](#判断目录是否为空)
34
+ 4. [分片上传 (upload_slice)](#文件分片上传)
35
+ 1. [分片上传大文件 (upload_slice)](#大文件分片上传)
36
+ 2. [分片上传初始化 (init_slice_upload)](#分片上传初始化)
37
+ 3. [分片上传数据 (upload_part)](#分片上传数据)
38
+ 4. [命令行工具 (qcloud-cos)](#命令行工具)
39
+ 1. [配置 (qcloud-cos config)](#命令行配置)
40
+ 2. [查看信息 (qcloud-cos info)](#info)
41
+ 3. [列出文件 (qcloud-cos list)](#list)
42
+ 4. [上传文件或者目录 (qcloud-cos upload)](#upload)
43
+ 5. [下载文件或者目录 (qcloud-cos download)](#download)
44
+ 6. [删除文件或者目录 (qcloud-cos remove)](#remove)
45
+ 3. [其它资源](#其它资源)
35
46
 
36
47
 
37
48
  ## 开发准备
@@ -539,63 +550,6 @@ path = "/myFolder/test.log";
539
550
  result = QcloudCos.upload(path, file, biz_attr: 'attr')
540
551
  ```
541
552
 
542
- #### 文件分片上传
543
-
544
- 1. 接口说明
545
-
546
- 用于较大文件(一般大于8MB)的上传,调用者可以通过此接口上传较大文件并获得文件的url和唯一标识resource_path(用于调用其他api)。
547
-
548
- 2. 方法
549
-
550
- ```ruby
551
- QcloudCos.upload_slice(dst_path, src_path, options = {})
552
- ```
553
-
554
- 3. 参数和返回值
555
-
556
- 参数说明:
557
-
558
-
559
- |参数名|类型 |必须 |默认值 |参数描述|
560
- |-----|----|-----|------|-------|
561
- | dst_path | String|是 |无 |文件在COS服务端的全路径,不包括/appid/bucketname|
562
- | src_path | String |是 |无 |本地要上传文件的全路径|
563
- | options | Hash | 否 | 无 | 额外参数
564
- | options['bucket'] | String| 否 | 配置的默认 bucket | Bucket 名称|
565
- | options['biz_attr'] | String| 否 | 无 | 文件属性,业务端自己维护 |
566
- | options['slice_size'] |Integer |否 | 3M|分片大小,用户可以根据网络状况自行设置|
567
- | options['session'] |String |否 |null |如果是断点续传, 则带上(唯一标识此文件传输过程的id, 由后台下发, 调用方透传)|
568
-
569
-
570
- 返回值, Hash:
571
-
572
-
573
- |参数名 |类型 |必然返回 |参数描述 |
574
- |------|----|--------|--------|
575
- |code |Integer |是 |错误码,成功时为0|
576
- |message |String |是 |错误信息|
577
- |data |Array |是 |返回数据|
578
- |data['access_url'] | String| 是 |生成的文件下载url|
579
- |data['url'] |String |是 |操作文件的url|
580
- |data['resource_path'] |String |是 |资源路径. 格式:/appid/bucket/xxx|
581
-
582
- API 请求错误,则抛出 RequestError 异常
583
-
584
-
585
- |参数名 |类型 |参数描述 |
586
- |------|----|--------|
587
- |code | Int| API 错误码|
588
- |message | String| 错误信息|
589
- |original_response | Response | 原始返回结果|
590
-
591
- 示例代码:
592
-
593
- ```ruby
594
- src_path= "/data/test.mp4"
595
- dst_path = "/myFolder/test.mp4"
596
- result = QcloudCos.upload_slice(dst_path, src_path)
597
- ```
598
-
599
553
  #### 查看文件和文件夹数目
600
554
 
601
555
  1. 接口说明
@@ -753,9 +707,380 @@ API 请求错误,则抛出 RequestError 异常
753
707
  ```ruby
754
708
  path = "/myFolder/test.mp4"
755
709
  result = QcloudCos.public_url(path)
756
- ```
710
+ ```
711
+
712
+
713
+ ## 分片上传
714
+
715
+ 分片上传在大文件上传和断点续传方面有很大的作用。我们主要提供了三个接口来帮助你完成上传。
716
+
717
+ ### 大文件分片上传
718
+
719
+ 1. 接口说明
720
+
721
+ 用于较大文件的上传,调用者可以通过此接口上传较大文件并获得文件的url。
722
+ 该接口还还支持断点续传,如果由于网络原因,导致了上传失败,只需要重试即可在自动在之前中断的位置继续上传。
723
+
724
+ 如果你还需要更进一步的定制需求,可以使用更底层的接口:[init_slice_upload]() + [upload_part]()
725
+
726
+ 2. 方法
727
+
728
+ ```ruby
729
+ QcloudCos.upload_slice(dst_path, src_path, options = {}, &block)
730
+ ```
731
+
732
+ 3. 参数和返回值
733
+
734
+ 参数说明:
735
+
736
+
737
+ |参数名|类型 |必须 |默认值 |参数描述|
738
+ |-----|----|-----|------|-------|
739
+ | dst_path | String|是 |无 |文件在COS服务端的全路径,不包括/appid/bucketname|
740
+ | src_path | String |是 |无 |本地要上传文件的全路径|
741
+ | block | Blockk |否 |无 |如果需要显示进度,可以传递一个 Block,Block 需要接受一个参数,是 0~1 的一个小数,表示当前进度|
742
+ | options | Hash | 否 | 无 | 额外参数
743
+ | options['bucket'] | String| 否 | 配置的默认 bucket | Bucket 名称|
744
+ | options['biz_attr'] | String| 否 | 无 | 文件属性,业务端自己维护 |
745
+ | options['slice_size'] |Integer |否 | 3M|分片大小,用户可以根据网络状况自行设置|
746
+ | options['session'] |String |否 |null |如果是断点续传, 则带上(唯一标识此文件传输过程的id, 由后台下发, 调用方透传)|
747
+
748
+
749
+ 返回值, Hash:
750
+
751
+
752
+ |参数名 |类型 |必然返回 |参数描述 |
753
+ |------|----|--------|--------|
754
+ |code |Integer |是 |错误码,成功时为0|
755
+ |message |String |是 |错误信息|
756
+ |data |Array |是 |返回数据|
757
+ |data['access_url'] | String| 是 |生成的文件下载url|
758
+ |data['url'] |String |是 |操作文件的url|
759
+ |data['resource_path'] |String |是 |资源路径. 格式:/appid/bucket/xxx|
760
+
761
+ API 请求错误,则抛出 RequestError 异常
762
+
763
+
764
+ |参数名 |类型 |参数描述 |
765
+ |------|----|--------|
766
+ |code | Int| API 错误码|
767
+ |message | String| 错误信息|
768
+ |original_response | Response | 原始返回结果|
769
+
770
+ 示例代码:
771
+
772
+ ```ruby
773
+ src_path= "/data/test.mp4"
774
+ dst_path = "/myFolder/test.mp4"
775
+ result = QcloudCos.upload_slice(dst_path, src_path)
776
+ result = QcloudCos.upload_slice(dst_path, src_path) do |pr|
777
+ puts "uploaded #{pr * 100}%"
778
+ end
779
+ ```
780
+
781
+ ### 分片上传初始化
782
+
783
+ 1. 接口说明
784
+
785
+ 初始化分片上传,正常会返回分片上传 session ID。
786
+
787
+ 注意:
788
+
789
+ + 如果该文件 sha 值已存在,则直接返回成功,你可以根据结果中是否包含 data['url'] 判断。
790
+ + 如果该文件上次分片上传没有成功,data['offset'] 表示了上次上传的位置,你可以从该位置开始上传。
791
+ + 如果想断点续传,则需要传递上一次 session ID.
792
+
793
+ 2. 方法
794
+
795
+ ```ruby
796
+ QcloudCos.init_slice_upload(path, filesize, sha, options = {})
797
+ ```
798
+
799
+ 3. 参数和返回值
800
+
801
+ 参数说明:
802
+
803
+
804
+ |参数名|类型 |必须 |默认值 |参数描述|
805
+ |-----|----|-----|------|-------|
806
+ | path | String|是 |无 |文件在COS服务端的全路径,不包括/appid/bucketname|
807
+ | filesize | Integer |是 |无 |本地要上传文件大小|
808
+ | sha | String |是 |无 |本地要上传文件 sha1 值 |
809
+ | options | Hash | 否 | 无 | 额外参数
810
+ | options['bucket'] | String| 否 | 配置的默认 bucket | Bucket 名称|
811
+ | options['biz_attr'] | String| 否 | 无 | 文件属性,业务端自己维护 |
812
+ | options['slice_size'] |Integer |否 | 3M|分片大小,用户可以根据网络状况自行设置|
813
+ | options['session'] |String |否 |null |如果是断点续传, 则带上(唯一标识此文件传输过程的id, 由后台下发, 调用方透传)|
814
+
815
+
816
+ 返回值, Hash:
817
+
818
+
819
+ |参数名 |类型 |必然返回 |参数描述 |
820
+ |------|----|--------|--------|
821
+ |code |Integer |是 |错误码,成功时为0|
822
+ |message |String |是 |错误信息|
823
+ |data |Hash |是 |返回数据|
824
+ |data['access_url'] | String| 否 |生成的文件下载url|
825
+ |data['url'] |String |否 |操作文件的url|
826
+ |data['resource_path'] |String |否 |资源路径. 格式:/appid/bucket/xxx|
827
+
828
+ API 请求错误,则抛出 RequestError 异常
829
+
830
+
831
+ |参数名 |类型 |参数描述 |
832
+ |------|----|--------|
833
+ |code | Int| API 错误码|
834
+ |message | String| 错误信息|
835
+ |original_response | Response | 原始返回结果|
836
+
837
+ 示例代码:
838
+
839
+ ```ruby
840
+ file = File.new("/data/test.mp4")
841
+ filesize = file.size
842
+ sha = Digest::SHA1.file('/data/test.mp4').hexdigest
843
+ dst_path = "/myFolder/test.mp4"
844
+ result = QcloudCos.init_slice_upload(dst_path, filesize, sha) # { data: { session: 'dsfasfda' }
845
+ ```
846
+
847
+ ### 分片上传数据
848
+
849
+ 1. 接口说明
850
+
851
+ 分片上传数据,初始化之后可以分片上传数据,文件上传成功会返回文件的 url。
852
+
853
+ 2. 方法
854
+
855
+ ```ruby
856
+ QcloudCos.upload_part(path, session, offset, content, options = {})
857
+ ```
858
+
859
+ 3. 参数和返回值
860
+
861
+ 参数说明:
862
+
863
+
864
+ |参数名|类型 |必须 |默认值 |参数描述|
865
+ |-----|----|-----|------|-------|
866
+ | path | String|是 |无 |文件在COS服务端的全路径,不包括/appid/bucketname|
867
+ | session | Integer |是 |无 |本次分片上传的 session ID, 初始化的时候会返回|
868
+ | offset | String |是 |无 |本地要上传的位移|
869
+ | content | String |是 |无 |本地要上传的内容 |
870
+ | options | Hash | 否 | 无 | 额外参数
871
+ | options['bucket'] | String| 否 | 配置的默认 bucket | Bucket 名称|
872
+
873
+
874
+ 返回值, Hash:
875
+
876
+
877
+ |参数名 |类型 |必然返回 |参数描述 |
878
+ |------|----|--------|--------|
879
+ |code |Integer |是 |错误码,成功时为0|
880
+ |message |String |是 |错误信息|
881
+ |data |Hash |是 |返回数据|
882
+ |data['access_url'] | String| 否 |生成的文件下载url|
883
+ |data['url'] |String |否 |操作文件的url|
884
+ |data['resource_path'] |String |否 |资源路径. 格式:/appid/bucket/xxx|
885
+
886
+ API 请求错误,则抛出 RequestError 异常
887
+
888
+
889
+ |参数名 |类型 |参数描述 |
890
+ |------|----|--------|
891
+ |code | Int| API 错误码|
892
+ |message | String| 错误信息|
893
+ |original_response | Response | 原始返回结果|
894
+
895
+ 示例代码:
896
+
897
+ ```ruby
898
+ session = 'dsfasfda'
899
+ result = QcloudCos.upload_part(dst_path, session, 100, 'Hello')
900
+ ```
901
+
902
+ ## 命令行工具
903
+
904
+ 为了更方便地管理你的 COS,我们提供了命令行工具。
905
+
906
+ 我们主要提供了五个基本命令: info, list, upload, download, remove 来完成你的操作
907
+
908
+ ```
909
+ $ qcloud-cos help
910
+
911
+ NAME:
912
+
913
+ qcloud-cos
914
+
915
+ DESCRIPTION:
916
+
917
+ command-line tool for Qcloud COS
918
+
919
+ COMMANDS:
920
+
921
+ config Init config, eg: qcloud-cos config
922
+ download Download objects from COS
923
+ help Display global or [command] help documentation
924
+ info Obtain information
925
+ list List objects under [dest_path]
926
+ remove Remove objects from COS
927
+ upload Upload file or folder to COS
928
+
929
+ GLOBAL OPTIONS:
930
+
931
+ -h, --help
932
+ Display help documentation
933
+
934
+ -v, --version
935
+ Display version information
936
+
937
+ -t, --trace
938
+ Display backtrace when an error occurs
939
+ ```
940
+
941
+ ### 命令行配置
942
+
943
+ 在使用之前,你需要先做一些配置,最快速的方式是使用 `qcloud-cos config` 命令:
944
+
945
+ ```
946
+ $ qcloud-cos config
947
+ Qcloud COS APP ID:
948
+ Qcloud COS Secret ID:
949
+ Qcloud COS Secret Key:
950
+ Default Qcloud COS Endpoint [http://web.file.myqcloud.com/files/v1/]:
951
+ Default Qcloud COS Bucket:
952
+ ```
953
+
954
+ 它会自动在当前目录下生成一个 `.qcloud-cos.yml` 配置文件。
955
+
956
+ 如果不使用配置文件,你也可以使用环境变量:
957
+
958
+ ```
959
+ export QCLOUD_COS_APP_ID='<your-app-id>'
960
+ export QCLOUD_COS_SECRET_ID='<your-secret-id>'
961
+ export QCLOUD_COS_SECRET_KEY='<your-secret-key>'
962
+ export QCLOUD_COS_ENDPOINT='http://web.file.myqcloud.com/files/v1/'
963
+ export QCLOUD_COS_BUCKET='<your-bucket-name>'
964
+ export QCLOUD_COS_SSL_CA_FILE='<your-ssl-ca-file-path>'
965
+ ```
966
+
967
+ ***注意:环境变量会覆盖配置文件中的设置***
968
+
969
+
970
+ ### info
971
+
972
+ 查看 Bucket,文件或者文件夹信息
973
+
974
+ 基本用法: `qcloud-cos info [options] [dest_path]`
975
+
976
+ 使用范例:
977
+
978
+ ```
979
+ # 查看 Bucket 信息
980
+ $ qcloud-cos info
981
+
982
+ # 查看 /production.log 信息
983
+ $ qcloud-cos info /production.log
984
+
985
+ # 查看 /test/ 信息
986
+ $ qcloud-cos info /test/
987
+
988
+ # 查看 bucket2 上的 /production.log 信息
989
+ $ qcloud-cos info --bucket bucket2 /production.log
990
+ ```
991
+
992
+ ### list
993
+
994
+ 列出文件或者文件夹
995
+
996
+ 基本用法: `qcloud-cos list [options] [dest_path]`
997
+
998
+ 使用范例:
999
+
1000
+ ```
1001
+ # 列出 / 下面的所有对象
1002
+ $ qcloud-cos list
1003
+
1004
+ # 列出 /test/ 下面的所有对象
1005
+ $ qcloud-cos list /test/
1006
+
1007
+ # 列出 /test/ 下面的前 10 个对象
1008
+ $ qcloud-cos list --num 10 /test/
1009
+
1010
+ # 列出 bucket2 的 /test/ 下面的所有对象
1011
+ $ qcloud-cos list --bucket bucket2 /test/
1012
+ ```
1013
+
1014
+ ### upload
1015
+
1016
+ 上传文件或者目录到 COS
1017
+
1018
+ 基本用法: `qcloud-cos upload [options] file [dest_path]`
1019
+
1020
+ 使用范例:
1021
+
1022
+ ```
1023
+ # 把 production.log 上传到 /
1024
+ $ qcloud-cos upload production.log
1025
+
1026
+ # 把 production.log 上传到 /data/ 下面
1027
+ $ qcloud-cos upload production.log /data/
1028
+
1029
+ # 把 ./test/ 整个文件夹上传到 /data/ 下面
1030
+ $ qcloud-cos upload test/ /data/
1031
+
1032
+ # 把 ./test/ 整个文件夹上传到 bucket2 的 /data/ 下面
1033
+ $ qcloud-cos upload --bucket bucket2 test/ /data/
1034
+ ```
1035
+
1036
+ ### download
1037
+
1038
+ 下载文件或者目录
1039
+
1040
+ 基本用法: `qcloud-cos download [options] dest_path [save_path]`
1041
+
1042
+ 使用范例:
1043
+
1044
+ ```
1045
+ # 把 /data/production.log 下载到当前目录
1046
+ $ qcloud-cos download /data/production.log
1047
+
1048
+ # 把 /data/production.log 下载到 ./data/ 下
1049
+ $ qcloud-cos download /data/production.log ./data
1050
+
1051
+ # 把 /data/test/ 整个目录下载并保存到 ./data/ 目录下面
1052
+ $ qcloud-cos download /data/test/ ./data
1053
+
1054
+ # 把 bucket2 下的 /data/test/ 整个目录下载并保存到 ./data/ 下面
1055
+ $ qcloud-cos download --bucket bucket2 /data/test/ ./data
1056
+ ```
1057
+
1058
+
1059
+ ### remove
1060
+
1061
+ 删除目录或者文件夹
1062
+
1063
+ 基本用法: `qcloud-cos remove [options] dest_path`
1064
+
1065
+ 使用范例:
1066
+
1067
+ ```
1068
+ # 删除文件/data/production.log
1069
+ $ qcloud-cos remove /data/production.log
1070
+
1071
+ # 删除目录 /data/test/, 目录非空会失败
1072
+ $ qcloud-cos remove /data/test/
1073
+
1074
+ # 级联删除目录 /data/test/
1075
+ $ qcloud-cos remove --recursive /data/test/
1076
+
1077
+ # 删除 bucket2 下面的目录 /data/test/
1078
+ $ qcloud-cos download --bucket bucket2 /data/test/
1079
+ ```
1080
+
1081
+
757
1082
 
758
1083
  ## 其它资源
759
1084
 
760
- + [RDoc 文档](http://www.rubydoc.info/gems/qcloud_cos/0.1.0)
1085
+ + [RDoc 文档](http://www.rubydoc.info/gems/qcloud_cos/0.3.0)
761
1086
  + [腾讯 COS 详细文档](http://www.qcloud.com/doc/product/227/%E4%BA%A7%E5%93%81%E4%BB%8B%E7%BB%8D)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qcloud_cos
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Newell Zhu
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-29 00:00:00.000000000 Z
11
+ date: 2016-01-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -52,6 +52,34 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: commander
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: awesome_print
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: bundler
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -153,7 +181,8 @@ dependencies:
153
181
  description: Ruby SDK For QCloud COS, Enjoy it!
154
182
  email:
155
183
  - zlx.star@gmail.com
156
- executables: []
184
+ executables:
185
+ - qcloud-cos
157
186
  extensions: []
158
187
  extra_rdoc_files: []
159
188
  files:
@@ -165,10 +194,12 @@ files:
165
194
  - README.md
166
195
  - Rakefile
167
196
  - bin/console
197
+ - bin/qcloud-cos
168
198
  - bin/setup
169
199
  - lib/qcloud_cos.rb
170
200
  - lib/qcloud_cos/api.rb
171
201
  - lib/qcloud_cos/authorization.rb
202
+ - lib/qcloud_cos/cli.rb
172
203
  - lib/qcloud_cos/configuration.rb
173
204
  - lib/qcloud_cos/convenient_api.rb
174
205
  - lib/qcloud_cos/error.rb
@@ -195,9 +226,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
195
226
  version: '0'
196
227
  required_rubygems_version: !ruby/object:Gem::Requirement
197
228
  requirements:
198
- - - ">="
229
+ - - ">"
199
230
  - !ruby/object:Gem::Version
200
- version: '0'
231
+ version: 1.3.1
201
232
  requirements: []
202
233
  rubyforge_project:
203
234
  rubygems_version: 2.2.0