qcloud_cos 0.3.0 → 0.4.0.pre

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