aliyun-sdk 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -0
- data/examples/aliyun/oss/bucket.rb +144 -0
- data/examples/aliyun/oss/object.rb +182 -0
- data/examples/aliyun/oss/resumable_download.rb +40 -0
- data/examples/aliyun/oss/resumable_upload.rb +46 -0
- data/examples/aliyun/oss/streaming.rb +124 -0
- data/lib/aliyun/oss/bucket.rb +78 -23
- data/lib/aliyun/oss/client.rb +2 -0
- data/lib/aliyun/oss/download.rb +62 -27
- data/lib/aliyun/oss/http.rb +6 -2
- data/lib/aliyun/oss/iterator.rb +18 -0
- data/lib/aliyun/oss/logging.rb +5 -2
- data/lib/aliyun/oss/multipart.rb +3 -2
- data/lib/aliyun/oss/object.rb +1 -1
- data/lib/aliyun/oss/protocol.rb +17 -21
- data/lib/aliyun/oss/upload.rb +58 -19
- data/lib/aliyun/oss/util.rb +1 -0
- data/lib/aliyun/oss/version.rb +1 -1
- data/spec/aliyun/oss/client/bucket_spec.rb +88 -2
- data/spec/aliyun/oss/client/resumable_download_spec.rb +8 -5
- data/spec/aliyun/oss/client/resumable_upload_spec.rb +7 -4
- data/spec/aliyun/oss/multipart_spec.rb +0 -10
- data/spec/aliyun/oss/object_spec.rb +9 -10
- data/tests/test_content_type.rb +100 -0
- data/tests/test_large_file.rb +66 -0
- data/tests/test_multipart.rb +105 -0
- data/tests/test_object_key.rb +71 -0
- data/tests/test_resumable.rb +41 -0
- metadata +19 -2
@@ -75,8 +75,9 @@ module Aliyun
|
|
75
75
|
expect(File.exist?("#{@file}.cpt")).to be false
|
76
76
|
expect(Dir.glob("#{@file}.part.*").empty?).to be true
|
77
77
|
|
78
|
-
expect(File.read(@file)
|
79
|
-
|
78
|
+
expect(File.read(@file).lines)
|
79
|
+
.to match_array((1..10).map{ |i| mock_object(i) })
|
80
|
+
expect(prg.size).to eq(10)
|
80
81
|
end
|
81
82
|
|
82
83
|
it "should resume when download part fails" do
|
@@ -103,7 +104,8 @@ module Aliyun
|
|
103
104
|
success = false
|
104
105
|
4.times do
|
105
106
|
begin
|
106
|
-
@bucket.resumable_download(
|
107
|
+
@bucket.resumable_download(
|
108
|
+
@object_key, @file, :part_size => 10, :threads => 1)
|
107
109
|
success = true
|
108
110
|
rescue
|
109
111
|
# pass
|
@@ -158,7 +160,8 @@ module Aliyun
|
|
158
160
|
success = false
|
159
161
|
4.times do
|
160
162
|
begin
|
161
|
-
@bucket.resumable_download(
|
163
|
+
@bucket.resumable_download(
|
164
|
+
@object_key, @file, :part_size => 10, :threads => 1)
|
162
165
|
success = true
|
163
166
|
rescue
|
164
167
|
# pass
|
@@ -197,7 +200,7 @@ module Aliyun
|
|
197
200
|
begin
|
198
201
|
@bucket.resumable_download(
|
199
202
|
@object_key, @file, :part_size => 10,
|
200
|
-
:cpt_file => cpt_file, :disable_cpt => true)
|
203
|
+
:cpt_file => cpt_file, :disable_cpt => true, :threads => 1)
|
201
204
|
success = true
|
202
205
|
rescue
|
203
206
|
# pass
|
@@ -96,7 +96,7 @@ module Aliyun
|
|
96
96
|
:post, /#{object_url}\?uploadId.*/).times(1)
|
97
97
|
|
98
98
|
expect(File.exist?("#{@file}.cpt")).to be false
|
99
|
-
expect(prg).to
|
99
|
+
expect(prg.size).to eq(10)
|
100
100
|
end
|
101
101
|
|
102
102
|
it "should restart when begin txn fails" do
|
@@ -149,7 +149,8 @@ module Aliyun
|
|
149
149
|
success = false
|
150
150
|
4.times do
|
151
151
|
begin
|
152
|
-
@bucket.resumable_upload(
|
152
|
+
@bucket.resumable_upload(
|
153
|
+
@object_key, @file, part_size: 10, threads: 1)
|
153
154
|
success = true
|
154
155
|
rescue
|
155
156
|
# pass
|
@@ -206,7 +207,8 @@ module Aliyun
|
|
206
207
|
success = false
|
207
208
|
4.times do
|
208
209
|
begin
|
209
|
-
@bucket.resumable_upload(
|
210
|
+
@bucket.resumable_upload(
|
211
|
+
@object_key, @file, part_size: 10, threads: 1)
|
210
212
|
success = true
|
211
213
|
rescue
|
212
214
|
# pass
|
@@ -251,7 +253,8 @@ module Aliyun
|
|
251
253
|
success = false
|
252
254
|
3.times do
|
253
255
|
begin
|
254
|
-
@bucket.resumable_upload(
|
256
|
+
@bucket.resumable_upload(
|
257
|
+
@object_key, @file, part_size: 10, threads: 1)
|
255
258
|
success = true
|
256
259
|
rescue
|
257
260
|
# pass
|
@@ -38,7 +38,6 @@ module Aliyun
|
|
38
38
|
xml.ListMultipartUploadsResult {
|
39
39
|
{
|
40
40
|
:prefix => 'Prefix',
|
41
|
-
:delimiter => 'Delimiter',
|
42
41
|
:limit => 'MaxUploads',
|
43
42
|
:id_marker => 'UploadIdMarker',
|
44
43
|
:next_id_marker => 'NextUploadIdMarker',
|
@@ -414,7 +413,6 @@ module Aliyun
|
|
414
413
|
query = {
|
415
414
|
'uploads' => '',
|
416
415
|
'prefix' => 'foo-',
|
417
|
-
'delimiter' => '-',
|
418
416
|
'upload-id-marker' => 'id-marker',
|
419
417
|
'key-marker' => 'key-marker',
|
420
418
|
'max-uploads' => 10,
|
@@ -426,7 +424,6 @@ module Aliyun
|
|
426
424
|
@protocol.list_multipart_uploads(
|
427
425
|
@bucket,
|
428
426
|
:prefix => 'foo-',
|
429
|
-
:delimiter => '-',
|
430
427
|
:id_marker => 'id-marker',
|
431
428
|
:key_marker => 'key-marker',
|
432
429
|
:limit => 10,
|
@@ -442,7 +439,6 @@ module Aliyun
|
|
442
439
|
query = {
|
443
440
|
'uploads' => '',
|
444
441
|
'prefix' => 'foo-',
|
445
|
-
'delimiter' => '-',
|
446
442
|
'upload-id-marker' => 'id-marker',
|
447
443
|
'key-marker' => 'key-marker',
|
448
444
|
'max-uploads' => 100,
|
@@ -459,7 +455,6 @@ module Aliyun
|
|
459
455
|
|
460
456
|
return_more = {
|
461
457
|
:prefix => 'foo-',
|
462
|
-
:delimiter => '-',
|
463
458
|
:id_marker => 'id-marker',
|
464
459
|
:key_marker => 'key-marker',
|
465
460
|
:next_id_marker => 'next-id-marker',
|
@@ -474,7 +469,6 @@ module Aliyun
|
|
474
469
|
txns, more = @protocol.list_multipart_uploads(
|
475
470
|
@bucket,
|
476
471
|
:prefix => 'foo-',
|
477
|
-
:delimiter => '-',
|
478
472
|
:id_marker => 'id-marker',
|
479
473
|
:key_marker => 'key-marker',
|
480
474
|
:limit => 100,
|
@@ -492,7 +486,6 @@ module Aliyun
|
|
492
486
|
query = {
|
493
487
|
'uploads' => '',
|
494
488
|
'prefix' => 'foo-',
|
495
|
-
'delimiter' => '-',
|
496
489
|
'upload-id-marker' => 'id-marker',
|
497
490
|
'key-marker' => 'key-marker',
|
498
491
|
'max-uploads' => 100,
|
@@ -516,7 +509,6 @@ module Aliyun
|
|
516
509
|
|
517
510
|
return_more = {
|
518
511
|
:prefix => 'foo-',
|
519
|
-
:delimiter => '中国のruby',
|
520
512
|
:id_marker => 'id-marker',
|
521
513
|
:key_marker => '杭州のruby',
|
522
514
|
:next_id_marker => 'next-id-marker',
|
@@ -528,7 +520,6 @@ module Aliyun
|
|
528
520
|
|
529
521
|
es_more = {
|
530
522
|
:prefix => 'foo-',
|
531
|
-
:delimiter => CGI.escape('中国のruby'),
|
532
523
|
:id_marker => 'id-marker',
|
533
524
|
:key_marker => CGI.escape('杭州のruby'),
|
534
525
|
:next_id_marker => 'next-id-marker',
|
@@ -545,7 +536,6 @@ module Aliyun
|
|
545
536
|
txns, more = @protocol.list_multipart_uploads(
|
546
537
|
@bucket,
|
547
538
|
:prefix => 'foo-',
|
548
|
-
:delimiter => '-',
|
549
539
|
:id_marker => 'id-marker',
|
550
540
|
:key_marker => 'key-marker',
|
551
541
|
:limit => 100,
|
@@ -54,16 +54,15 @@ module Aliyun
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def mock_delete(objects, opts = {})
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
end.to_xml
|
57
|
+
# It may have invisible chars in object key which will corrupt
|
58
|
+
# libxml. So we're constructing xml body manually here.
|
59
|
+
body = '<?xml version="1.0"?>'
|
60
|
+
body << '<Delete>'
|
61
|
+
body << '<Quiet>' << (opts[:quiet]? true : false).to_s << '</Quiet>'
|
62
|
+
objects.each { |k|
|
63
|
+
body << '<Object><Key>' << k << '</Key></Object>'
|
64
|
+
}
|
65
|
+
body << '</Delete>'
|
67
66
|
end
|
68
67
|
|
69
68
|
def mock_delete_result(deleted, opts = {})
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'yaml'
|
3
|
+
$LOAD_PATH.unshift(File.expand_path("../../lib", __FILE__))
|
4
|
+
require 'aliyun/oss'
|
5
|
+
|
6
|
+
class TestContentType < Minitest::Test
|
7
|
+
def setup
|
8
|
+
Aliyun::OSS::Logging.set_log_level(Logger::DEBUG)
|
9
|
+
conf_file = '~/.oss.yml'
|
10
|
+
conf = YAML.load(File.read(File.expand_path(conf_file)))
|
11
|
+
client = Aliyun::OSS::Client.new(
|
12
|
+
:endpoint => conf['endpoint'],
|
13
|
+
:cname => conf['cname'],
|
14
|
+
:access_key_id => conf['id'],
|
15
|
+
:access_key_secret => conf['key'])
|
16
|
+
@bucket = client.get_bucket(conf['bucket'])
|
17
|
+
|
18
|
+
@types = {
|
19
|
+
"html" => "text/html",
|
20
|
+
"js" => "application/javascript",
|
21
|
+
"xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
22
|
+
"xltx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.template",
|
23
|
+
"potx" => "application/vnd.openxmlformats-officedocument.presentationml.template",
|
24
|
+
"ppsx" => "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
|
25
|
+
"pptx" => "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
26
|
+
"sldx" => "application/vnd.openxmlformats-officedocument.presentationml.slide",
|
27
|
+
"docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
28
|
+
"dotx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.template",
|
29
|
+
"xlam" => "application/vnd.ms-excel.addin.macroEnabled.12",
|
30
|
+
"xlsb" => "application/vnd.ms-excel.sheet.binary.macroEnabled.12",
|
31
|
+
"apk" => "application/vnd.android.package-archive",
|
32
|
+
"" => "application/octet-stream"
|
33
|
+
}
|
34
|
+
|
35
|
+
@prefix = "tests/content_type/"
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_key(p, k)
|
39
|
+
"#{@prefix}#{p}obj" + (k.empty? ? "" : ".#{k}")
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_type_from_key
|
43
|
+
@types.each do |k, v|
|
44
|
+
key = get_key('from_key', k)
|
45
|
+
@bucket.put_object(key)
|
46
|
+
assert_equal v, @bucket.get_object(key).content_type
|
47
|
+
|
48
|
+
copy_key = get_key('copy.from_key', k)
|
49
|
+
@bucket.copy_object(key, copy_key)
|
50
|
+
assert_equal v, @bucket.get_object(copy_key).content_type
|
51
|
+
|
52
|
+
append_key = get_key('append.from_key', k)
|
53
|
+
@bucket.append_object(append_key, 0)
|
54
|
+
assert_equal v, @bucket.get_object(append_key).content_type
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_type_from_file
|
59
|
+
@types.each do |k, v|
|
60
|
+
upload_file = "/tmp/upload_file"
|
61
|
+
upload_file += ".#{k}" unless k.empty?
|
62
|
+
`touch #{upload_file}`
|
63
|
+
|
64
|
+
key = get_key('from_file', k)
|
65
|
+
@bucket.put_object(key, :file => upload_file)
|
66
|
+
assert_equal v, @bucket.get_object(key).content_type
|
67
|
+
|
68
|
+
append_key = get_key('append.from_file', k)
|
69
|
+
@bucket.append_object(append_key, 0, :file => upload_file)
|
70
|
+
assert_equal v, @bucket.get_object(append_key).content_type
|
71
|
+
|
72
|
+
multipart_key = get_key('multipart.from_file', k)
|
73
|
+
@bucket.resumable_upload(multipart_key, upload_file)
|
74
|
+
assert_equal v, @bucket.get_object(multipart_key).content_type
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_type_from_user
|
79
|
+
@types.each do |k, v|
|
80
|
+
upload_file = "/tmp/upload_file.html"
|
81
|
+
`touch #{upload_file}`
|
82
|
+
|
83
|
+
key = get_key('from_user', k)
|
84
|
+
@bucket.put_object(key, :file => upload_file, :content_type => v)
|
85
|
+
assert_equal v, @bucket.get_object(key).content_type
|
86
|
+
|
87
|
+
copy_key = get_key('copy.from_user', k)
|
88
|
+
@bucket.copy_object(key, copy_key, :content_type => v)
|
89
|
+
assert_equal v, @bucket.get_object(copy_key).content_type
|
90
|
+
|
91
|
+
append_key = get_key('append.from_user', k)
|
92
|
+
@bucket.append_object(append_key, 0, :file => upload_file, :content_type => v)
|
93
|
+
assert_equal v, @bucket.get_object(append_key).content_type
|
94
|
+
|
95
|
+
multipart_key = get_key('multipart.from_file', k)
|
96
|
+
@bucket.resumable_upload(multipart_key, upload_file, :content_type => v)
|
97
|
+
assert_equal v, @bucket.get_object(multipart_key).content_type
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'benchmark'
|
4
|
+
require 'yaml'
|
5
|
+
$LOAD_PATH.unshift(File.expand_path("../../lib", __FILE__))
|
6
|
+
require 'aliyun/oss'
|
7
|
+
|
8
|
+
class TestObjectKey < Minitest::Test
|
9
|
+
def setup
|
10
|
+
conf_file = '~/.oss.yml'
|
11
|
+
conf = YAML.load(File.read(File.expand_path(conf_file)))
|
12
|
+
client = Aliyun::OSS::Client.new(
|
13
|
+
:endpoint => conf['endpoint'],
|
14
|
+
:cname => conf['cname'],
|
15
|
+
:access_key_id => conf['id'],
|
16
|
+
:access_key_secret => conf['key'])
|
17
|
+
@bucket = client.get_bucket(conf['bucket'])
|
18
|
+
@prefix = 'tests/large_file/'
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_key(k)
|
22
|
+
@prefix + k
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_large_file_1gb
|
26
|
+
key = get_key("large_file_1gb")
|
27
|
+
Benchmark.bm(32) do |bm|
|
28
|
+
bm.report("Upload with put_object: ") do
|
29
|
+
@bucket.put_object(key, :file => './large_file_1gb')
|
30
|
+
end
|
31
|
+
|
32
|
+
bm.report("Upload with resumable_upload: ") do
|
33
|
+
@bucket.resumable_upload(key, './large_file_1gb')
|
34
|
+
end
|
35
|
+
|
36
|
+
bm.report("Download with get_object: ") do
|
37
|
+
@bucket.get_object(key, :file => './large_file_1gb')
|
38
|
+
end
|
39
|
+
|
40
|
+
bm.report("Download with resumable_download: ") do
|
41
|
+
@bucket.resumable_download(key, './large_file_1gb')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_large_file_8gb
|
47
|
+
key = get_key("large_file_8gb")
|
48
|
+
Benchmark.bm(32) do |bm|
|
49
|
+
bm.report("Upload with put_object: ") do
|
50
|
+
@bucket.put_object(key, :file => './large_file_8gb')
|
51
|
+
end
|
52
|
+
|
53
|
+
bm.report("Upload with resumable_upload: ") do
|
54
|
+
@bucket.resumable_upload(key, './large_file_8gb')
|
55
|
+
end
|
56
|
+
|
57
|
+
bm.report("Download with get_object: ") do
|
58
|
+
@bucket.get_object(key, :file => './large_file_8gb')
|
59
|
+
end
|
60
|
+
|
61
|
+
bm.report("Download with resumable_download: ") do
|
62
|
+
@bucket.resumable_download(key, './large_file_8gb')
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'yaml'
|
4
|
+
$LOAD_PATH.unshift(File.expand_path("../../lib", __FILE__))
|
5
|
+
require 'aliyun/oss'
|
6
|
+
|
7
|
+
class TestMultipart < Minitest::Unit::TestCase
|
8
|
+
def setup
|
9
|
+
conf_file = '~/.oss.yml'
|
10
|
+
conf = YAML.load(File.read(File.expand_path(conf_file)))
|
11
|
+
opts = {
|
12
|
+
endpoint: conf['endpoint'],
|
13
|
+
cname: conf['cname'],
|
14
|
+
access_key_id: conf['id'],
|
15
|
+
access_key_secret: conf['key'],
|
16
|
+
}
|
17
|
+
client = Aliyun::OSS::Client.new(opts)
|
18
|
+
@bucket_name = conf['bucket']
|
19
|
+
@bucket = client.get_bucket(@bucket_name)
|
20
|
+
@protocol = Aliyun::OSS::Protocol.new(Aliyun::OSS::Config.new(opts))
|
21
|
+
@prefix = 'tests/multipart/'
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_key(k)
|
25
|
+
@prefix + k
|
26
|
+
end
|
27
|
+
|
28
|
+
def clear_uploads
|
29
|
+
all = @bucket.list_uploads.to_a
|
30
|
+
all.each { |t| @bucket.abort_upload(t.id, t.object) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_key_marker
|
34
|
+
clear_uploads
|
35
|
+
|
36
|
+
# initiate 5 uploads
|
37
|
+
ids = []
|
38
|
+
5.times { |i|
|
39
|
+
id = @protocol.initiate_multipart_upload(@bucket_name, get_key("obj-#{i}"))
|
40
|
+
ids << id
|
41
|
+
}
|
42
|
+
|
43
|
+
all = @bucket.list_uploads(limit: 1).to_a
|
44
|
+
assert_equal ids, all.map(&:id)
|
45
|
+
|
46
|
+
after_1 = @bucket.list_uploads(key_marker: get_key("obj-0")).to_a
|
47
|
+
assert_equal ids[1, 5], after_1.map(&:id)
|
48
|
+
|
49
|
+
after_5 = @bucket.list_uploads(key_marker: get_key("obj-4")).to_a
|
50
|
+
assert after_5.empty?, after_5.to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_id_marker
|
54
|
+
clear_uploads
|
55
|
+
|
56
|
+
# initiate 5 uploads
|
57
|
+
ids = []
|
58
|
+
5.times { |i|
|
59
|
+
id = @protocol.initiate_multipart_upload(@bucket_name, get_key("object"))
|
60
|
+
ids << id
|
61
|
+
}
|
62
|
+
ids.sort!
|
63
|
+
|
64
|
+
all = @bucket.list_uploads.to_a
|
65
|
+
assert_equal ids, all.map(&:id)
|
66
|
+
|
67
|
+
# id_marker is ignored
|
68
|
+
after_1 = @bucket.list_uploads(id_marker: ids[0]).to_a
|
69
|
+
assert_equal ids, after_1.map(&:id)
|
70
|
+
|
71
|
+
# id_marker is ignored
|
72
|
+
after_5 = @bucket.list_uploads(id_marker: ids[4]).to_a
|
73
|
+
assert_equal ids, after_5.map(&:id)
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_id_key_marker
|
77
|
+
clear_uploads
|
78
|
+
|
79
|
+
# initiate 5 uploads
|
80
|
+
foo_ids = []
|
81
|
+
5.times { |i|
|
82
|
+
id = @protocol.initiate_multipart_upload(@bucket_name, get_key("foo"))
|
83
|
+
foo_ids << id
|
84
|
+
}
|
85
|
+
foo_ids.sort!
|
86
|
+
|
87
|
+
bar_ids = []
|
88
|
+
5.times { |i|
|
89
|
+
id = @protocol.initiate_multipart_upload(@bucket_name, get_key("bar"))
|
90
|
+
bar_ids << id
|
91
|
+
}
|
92
|
+
bar_ids.sort!
|
93
|
+
|
94
|
+
after_1 = @bucket.list_uploads(
|
95
|
+
id_marker: bar_ids[0], key_marker: get_key("bar"), limit: 1).to_a
|
96
|
+
assert_equal bar_ids[1, 5] + foo_ids, after_1.map(&:id)
|
97
|
+
|
98
|
+
after_5 = @bucket.list_uploads(
|
99
|
+
id_marker: bar_ids[4], key_marker: get_key("bar")).to_a
|
100
|
+
assert_equal foo_ids, after_5.map(&:id)
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_prefix
|
104
|
+
end
|
105
|
+
end
|