fastdfs-client 1.3.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +12 -9
- data/lib/fastdfs-client.rb +2 -1
- data/lib/fastdfs-client/client_proxy.rb +6 -4
- data/lib/fastdfs-client/cmd.rb +10 -0
- data/lib/fastdfs-client/extend_core.rb +5 -2
- data/lib/fastdfs-client/proto_common.rb +1 -1
- data/lib/fastdfs-client/socket.rb +4 -5
- data/lib/fastdfs-client/storage.rb +30 -20
- data/lib/fastdfs-client/tracker.rb +3 -3
- data/lib/fastdfs-client/utils.rb +0 -4
- data/lib/fastdfs-client/version.rb +1 -1
- data/spec/mock_tcp_socket.rb +25 -4
- data/spec/spec_helper.rb +1 -0
- data/spec/storage_spec.rb +18 -6
- data/spec/test_config.rb +1 -1
- data/spec/tracker_spec.rb +1 -1
- data/spec/upload.rb +59 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8009a29d5b18921a4b3d9f628a9f7eaea019635
|
4
|
+
data.tar.gz: ac88fd2d1e51070637b34496619e750ccda97d57
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 445d9a50ccb21df204e0210cb968610831e137352d94a2c2fc62504c48864af9ef28190f1552b0e38476d91a6621925d7361706616361c9e2da638874c21ea01
|
7
|
+
data.tar.gz: 928522790ed79785a931dd0ac000c5ee977f6f5329a5ff74102522a5da3a26ab3daf9271835fe41867deba809380867445e8b136e554d6cc267885b10305046e
|
data/README.md
CHANGED
@@ -21,18 +21,21 @@ fastdfs client for ruby
|
|
21
21
|
|
22
22
|
@storage = tracker.get_storage
|
23
23
|
|
24
|
-
@storage.
|
25
|
-
#result: {group_name: "group1", path: "m1/xfsd/fds.jpg"}
|
24
|
+
if @storage.is_a?(Fastdfs::Client::Storage)
|
26
25
|
|
27
|
-
|
26
|
+
@storage.upload(@file)
|
27
|
+
#result: {group_name: "group1", path: "m1/xfsd/fds.jpg"}
|
28
28
|
|
29
|
-
|
30
|
-
@storage.set_metadata(path, group_name, {author: "kaka", width: "300"}, flag)
|
29
|
+
@storage.delete(path, group_name)
|
31
30
|
|
32
|
-
|
33
|
-
|
31
|
+
# flag params [cover, merge]
|
32
|
+
@storage.set_metadata(path, group_name, {author: "kaka", width: "300"}, flag)
|
34
33
|
|
35
|
-
|
36
|
-
|
34
|
+
@storage.get_metadata(path, group_name)
|
35
|
+
#result: {author: "kaka", width: "300"}
|
36
|
+
|
37
|
+
@storage.download(path, group_name)
|
38
|
+
#result: #<Tempfile:/var/folders/m7/bt2j0rk54x555t44dpn4b7bm0000gn/T/test.jpg20160416-43738-1560vq3>
|
39
|
+
end
|
37
40
|
|
38
41
|
```
|
data/lib/fastdfs-client.rb
CHANGED
@@ -17,12 +17,14 @@ module Fastdfs
|
|
17
17
|
@socket = Socket.new(host, port, options[:socket])
|
18
18
|
end
|
19
19
|
|
20
|
-
def dispose(cmd,
|
20
|
+
def dispose(cmd, header = [], content = [], &block)
|
21
21
|
synchronize do
|
22
|
-
@socket.connection do
|
23
|
-
|
22
|
+
@socket.connection do
|
23
|
+
contents = Array(content)
|
24
|
+
body_len = contents.map{|c| c.bytes.size }.inject(header.length){|sum, x| sum + x }
|
25
|
+
full_header = ProtoCommon.header_bytes(cmd, body_len).concat(header)
|
24
26
|
@socket.write(cmd, full_header)
|
25
|
-
|
27
|
+
contents.each do |c|
|
26
28
|
@socket.write(cmd, c)
|
27
29
|
end
|
28
30
|
@socket.receive &block
|
data/lib/fastdfs-client/cmd.rb
CHANGED
@@ -9,6 +9,16 @@ module Fastdfs
|
|
9
9
|
GET_METADATA = 15
|
10
10
|
SET_METADATA = 13
|
11
11
|
DOWNLOAD_FILE = 14
|
12
|
+
|
13
|
+
MAPPING_NAME = {
|
14
|
+
101 => "GET STORAGE",
|
15
|
+
11 => "UPLOAD FILE",
|
16
|
+
101 => "RESP CODE",
|
17
|
+
12 => "DELETE FILE",
|
18
|
+
15 => "GET METADATA",
|
19
|
+
13 => "SET METADATA",
|
20
|
+
14 => "DOWNLOAD FILE"
|
21
|
+
}
|
12
22
|
end
|
13
23
|
|
14
24
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
class Array
|
3
2
|
def to_pack_long
|
4
3
|
self.each_with_index.inject(0){|s, item| s = s | (item[0] << (56 - (item[1] * 8))); s }
|
@@ -9,7 +8,6 @@ class Array
|
|
9
8
|
end
|
10
9
|
end
|
11
10
|
|
12
|
-
|
13
11
|
class NilClass
|
14
12
|
def blank?
|
15
13
|
true
|
@@ -28,6 +26,11 @@ class Object
|
|
28
26
|
end
|
29
27
|
end
|
30
28
|
|
29
|
+
class Integer
|
30
|
+
def to_eight_buffer
|
31
|
+
8.times.map{|i| (self >> (56 - 8 * i)) & 255}
|
32
|
+
end
|
33
|
+
end
|
31
34
|
|
32
35
|
class Hash
|
33
36
|
|
@@ -20,7 +20,7 @@ module Fastdfs
|
|
20
20
|
SET_METADATA_FLAG_MERGE = "M"
|
21
21
|
|
22
22
|
def self.header_bytes(cmd, hex_long, erron=0)
|
23
|
-
hex_bytes =
|
23
|
+
hex_bytes = hex_long.to_eight_buffer
|
24
24
|
header = hex_bytes.fill(0, hex_bytes.length...HEAD_LEN)
|
25
25
|
header[8] = cmd
|
26
26
|
header[9] = erron
|
@@ -7,7 +7,7 @@ module Fastdfs
|
|
7
7
|
module Client
|
8
8
|
|
9
9
|
class Socket
|
10
|
-
attr_accessor :
|
10
|
+
attr_accessor :socket, :host, :port
|
11
11
|
|
12
12
|
def initialize(host, port, options = {})
|
13
13
|
@host, @port = host, port
|
@@ -19,7 +19,6 @@ module Fastdfs
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def write(*args)
|
22
|
-
debugger if args[1] == 119
|
23
22
|
@cmd = args.shift
|
24
23
|
pkg = args.shift
|
25
24
|
|
@@ -60,9 +59,9 @@ module Fastdfs
|
|
60
59
|
private
|
61
60
|
def parseHeader
|
62
61
|
err_msg = nil
|
63
|
-
err_msg = "recv package size #{@header} is not equal #{@header_len}, cmd: #{@cmd}" unless @header.length == @header_len || err_msg
|
64
|
-
err_msg = "recv cmd: #{@header[8]} is not correct, expect recv code: #{CMD::RESP_CODE}, cmd: #{@cmd}" unless @header[8] == CMD::RESP_CODE || err_msg
|
65
|
-
err_msg = "recv erron #{@header[9]}, 0 is correct cmd: #{@cmd}" unless @header[9] == 0 || err_msg
|
62
|
+
err_msg = "recv package size #{@header} is not equal #{@header_len}, cmd: #{CMD::MAPPING_NAME[@cmd]}" unless @header.length == @header_len || err_msg
|
63
|
+
err_msg = "recv cmd: #{@header[8]} is not correct, expect recv code: #{CMD::RESP_CODE}, cmd: #{CMD::MAPPING_NAME[@cmd]}" unless @header[8] == CMD::RESP_CODE || err_msg
|
64
|
+
err_msg = "recv erron #{@header[9]}, 0 is correct cmd: #{CMD::MAPPING_NAME[@cmd]}" unless @header[9] == 0 || err_msg
|
66
65
|
{status: err_msg.nil?, err_msg: err_msg}
|
67
66
|
end
|
68
67
|
|
@@ -4,7 +4,7 @@ module Fastdfs
|
|
4
4
|
module Client
|
5
5
|
|
6
6
|
class Storage
|
7
|
-
attr_accessor :
|
7
|
+
attr_accessor :proxy, :options, :socket, :store_path
|
8
8
|
|
9
9
|
def initialize(host, port, store_path = nil, options = {})
|
10
10
|
@options = options || {}
|
@@ -12,17 +12,15 @@ module Fastdfs
|
|
12
12
|
|
13
13
|
@proxy = ClientProxy.new(host, port, @options[:socket])
|
14
14
|
@socket = @proxy.socket
|
15
|
-
@extname_len = ProtoCommon::EXTNAME_LEN
|
16
|
-
@size_len = ProtoCommon::SIZE_LEN
|
17
15
|
@store_path = store_path || 0
|
18
16
|
end
|
19
17
|
|
20
|
-
def upload(
|
21
|
-
|
22
|
-
size_byte =
|
23
|
-
content_len =
|
18
|
+
def upload(_file, options = {})
|
19
|
+
file, ext_name_bytes = convert_file_info(_file)
|
20
|
+
size_byte = [@store_path].concat(file.size.to_eight_buffer).full_fill(0, file_size_len)
|
21
|
+
content_len = file_size_len + extname_len + file.size
|
24
22
|
|
25
|
-
@proxy.dispose(CMD::UPLOAD_FILE,
|
23
|
+
@proxy.dispose(CMD::UPLOAD_FILE, size_byte + ext_name_bytes, IO.read(file)) do |body|
|
26
24
|
group_name_max_len = ProtoCommon::GROUP_NAME_MAX_LEN
|
27
25
|
|
28
26
|
res = {group_name: body[0...group_name_max_len].strip, path: body[group_name_max_len..-1]}
|
@@ -32,13 +30,13 @@ module Fastdfs
|
|
32
30
|
end
|
33
31
|
|
34
32
|
def delete(path, group_name = nil)
|
35
|
-
|
36
|
-
@proxy.dispose(CMD::DELETE_FILE,
|
33
|
+
header_bytes = group_path_bytes(path, group_name).flatten
|
34
|
+
@proxy.dispose(CMD::DELETE_FILE, header_bytes)
|
37
35
|
end
|
38
36
|
|
39
37
|
def get_metadata(path, group_name = nil)
|
40
|
-
|
41
|
-
@proxy.dispose(CMD::GET_METADATA,
|
38
|
+
header_bytes = group_path_bytes(path, group_name).flatten
|
39
|
+
@proxy.dispose(CMD::GET_METADATA, header_bytes) do |body|
|
42
40
|
res = body.split(ProtoCommon::RECORD_SEPERATOR).map do |c|
|
43
41
|
c.split(ProtoCommon::FILE_SEPERATOR)
|
44
42
|
end.flatten
|
@@ -54,9 +52,8 @@ module Fastdfs
|
|
54
52
|
|
55
53
|
def download(path, group_name = nil)
|
56
54
|
path_bytes = group_path_bytes(path, group_name).flatten
|
57
|
-
|
58
|
-
|
59
|
-
@proxy.dispose(CMD::DOWNLOAD_FILE, data.length, data) do |body|
|
55
|
+
header_bytes = 0.to_eight_buffer.concat(0.to_eight_buffer).concat(path_bytes)
|
56
|
+
@proxy.dispose(CMD::DOWNLOAD_FILE, header_bytes) do |body|
|
60
57
|
create_tempfile(path, body) if body
|
61
58
|
end
|
62
59
|
end
|
@@ -87,10 +84,9 @@ module Fastdfs
|
|
87
84
|
group_bytes, path_bytes = group_path_bytes(path, group_name)
|
88
85
|
meta_bytes = meta_to_bytes(options)
|
89
86
|
|
90
|
-
size_bytes =
|
91
|
-
|
92
|
-
|
93
|
-
@proxy.dispose(CMD::SET_METADATA, total, (size_bytes + flag.bytes + group_bytes + path_bytes), meta_bytes.pack("C*"))
|
87
|
+
size_bytes = path_bytes.length.to_eight_buffer.concat(meta_bytes.length.to_eight_buffer).full_fill(0, 16)
|
88
|
+
# total = size_bytes.length + flag.length + group_bytes.length + path_bytes.length + meta_bytes.length
|
89
|
+
@proxy.dispose(CMD::SET_METADATA, (size_bytes + flag.bytes + group_bytes + path_bytes), meta_bytes.pack("C*"))
|
94
90
|
end
|
95
91
|
|
96
92
|
def convert_meta_flag(flag)
|
@@ -117,7 +113,21 @@ module Fastdfs
|
|
117
113
|
tmp.close
|
118
114
|
tmp
|
119
115
|
end
|
120
|
-
|
116
|
+
|
117
|
+
def extname_len; ProtoCommon::EXTNAME_LEN end;
|
118
|
+
def file_size_len; ProtoCommon::SIZE_LEN end;
|
119
|
+
|
120
|
+
def convert_file_info(file)
|
121
|
+
if file.class.name == "ActionDispatch::Http::UploadedFile"
|
122
|
+
return file.tempfile, convert_extname_bytes(file.original_filename)
|
123
|
+
else
|
124
|
+
return file, convert_extname_bytes(file.path)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def convert_extname_bytes(file_name)
|
129
|
+
File.extname(file_name)[1..extname_len].to_s.bytes.full_fill(0, extname_len)
|
130
|
+
end
|
121
131
|
end
|
122
132
|
|
123
133
|
end
|
@@ -4,8 +4,8 @@ module Fastdfs
|
|
4
4
|
module Client
|
5
5
|
|
6
6
|
class Tracker
|
7
|
-
|
8
|
-
attr_accessor :
|
7
|
+
|
8
|
+
attr_accessor :options, :socket
|
9
9
|
|
10
10
|
def initialize(host, port, options = {})
|
11
11
|
@options = options
|
@@ -15,7 +15,7 @@ module Fastdfs
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def get_storage
|
18
|
-
res = @proxy.dispose(@cmd
|
18
|
+
res = @proxy.dispose(@cmd) do |body|
|
19
19
|
storage_ip = body[ProtoCommon::IPADDR].strip
|
20
20
|
storage_port = body[ProtoCommon::PORT].unpack("C*").to_pack_long
|
21
21
|
store_path = body[ProtoCommon::TRACKER_BODY_LEN-1].unpack("C*")[0]
|
data/lib/fastdfs-client/utils.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
1
|
module Utils
|
2
2
|
|
3
|
-
def self.number_to_buffer(num)
|
4
|
-
8.times.map{|i| (num >> (56 - 8 * i)) & 255}
|
5
|
-
end
|
6
|
-
|
7
3
|
def self.array_merge(arr1, arr2)
|
8
4
|
raise "argument must be array" unless arr1.is_a?(Array) || arr2.is_a?(Array)
|
9
5
|
arr2.each_with_index.map{|v, i| arr1[i] = v }
|
data/spec/mock_tcp_socket.rb
CHANGED
@@ -10,16 +10,28 @@ class MockTCPSocket
|
|
10
10
|
@recv_offset = 0
|
11
11
|
@connect_state = true
|
12
12
|
@cmd = nil
|
13
|
+
@content = []
|
14
|
+
@header = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def connection
|
18
|
+
@content = []
|
19
|
+
@header = []
|
13
20
|
end
|
14
21
|
|
15
22
|
def write(*args)
|
16
23
|
pkg = args[0].unpack("C*")
|
24
|
+
if @header.length <= 0
|
25
|
+
@header = pkg
|
26
|
+
else
|
27
|
+
@content.concat(pkg)
|
28
|
+
end
|
17
29
|
@cmd ||= pkg[8]
|
18
30
|
sleep(rand(0..4))
|
19
31
|
end
|
20
32
|
|
21
33
|
def recv(len)
|
22
|
-
sleep(rand(0..
|
34
|
+
sleep(rand(0..2))
|
23
35
|
data = case @cmd
|
24
36
|
when 101
|
25
37
|
gate_tracker(len)
|
@@ -55,7 +67,7 @@ class MockTCPSocket
|
|
55
67
|
|
56
68
|
group_name = Utils.array_merge([].fill(0, 0...16), TestConfig::GROUP_NAME.bytes)
|
57
69
|
ip = Utils.array_merge([].fill(0, 0...15), TestConfig::STORAGE_IP.bytes)
|
58
|
-
port =
|
70
|
+
port = TestConfig::STORAGE_PORT.to_i.to_eight_buffer
|
59
71
|
store_path = Array(TestConfig::STORE_PATH)
|
60
72
|
|
61
73
|
(header+group_name+ip+port+store_path)[@recv_offset...@recv_offset+len].pack("C*")
|
@@ -64,8 +76,9 @@ class MockTCPSocket
|
|
64
76
|
def upload_file(len)
|
65
77
|
header = ProtoCommon.header_bytes(CMD::RESP_CODE, 0)
|
66
78
|
group_name = Utils.array_merge([].fill(0, 0...16), TestConfig::GROUP_NAME.bytes)
|
67
|
-
|
68
|
-
|
79
|
+
path = path_replace_extname
|
80
|
+
file_path_bytes = path.bytes
|
81
|
+
res = (group_name + file_path_bytes)
|
69
82
|
header[7] = (header + res).length
|
70
83
|
res = (header + res)
|
71
84
|
|
@@ -95,4 +108,12 @@ class MockTCPSocket
|
|
95
108
|
header[7] = body.length
|
96
109
|
(header + body)[@recv_offset...@recv_offset+len].pack("C*")
|
97
110
|
end
|
111
|
+
|
112
|
+
private
|
113
|
+
def path_replace_extname
|
114
|
+
path = TestConfig::FILE_PATH
|
115
|
+
extname = File.extname(path)
|
116
|
+
path.gsub!(extname, ".#{@header[19..-1].reject{|i| i.zero? }.pack('C*')}")
|
117
|
+
path
|
118
|
+
end
|
98
119
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,6 +2,7 @@ require 'debugger'
|
|
2
2
|
require 'rspec'
|
3
3
|
require 'rspec/core'
|
4
4
|
require 'rspec/mocks'
|
5
|
+
require 'upload'
|
5
6
|
require File.expand_path('../../lib/fastdfs-client', __FILE__)
|
6
7
|
require File.expand_path('../test_config', __FILE__)
|
7
8
|
require File.expand_path('../mock_tcp_socket', __FILE__)
|
data/spec/storage_spec.rb
CHANGED
@@ -7,6 +7,12 @@ describe Fastdfs::Client::Storage do
|
|
7
7
|
|
8
8
|
let(:tracker){ FC::Tracker.new(host, port) }
|
9
9
|
let(:storage){ tracker.get_storage }
|
10
|
+
let(:tempfile) do
|
11
|
+
file = Tempfile.new([nil, "1.txt"])
|
12
|
+
file.write("testtest")
|
13
|
+
file.close
|
14
|
+
file
|
15
|
+
end
|
10
16
|
|
11
17
|
it "initialize the server" do
|
12
18
|
expect(FC::Socket).to receive(:new).with(host, port, nil)
|
@@ -26,10 +32,16 @@ describe Fastdfs::Client::Storage do
|
|
26
32
|
end
|
27
33
|
|
28
34
|
it "tempfile upload " do
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
35
|
+
res = storage.upload(tempfile)
|
36
|
+
expect(res[:status]).to be_truthy
|
37
|
+
expect(File.extname(res[:result][:path])).to eq(".txt")
|
38
|
+
end
|
39
|
+
|
40
|
+
it "ActionDispatch::Http::UploadedFile upload" do
|
41
|
+
file = ActionDispatch::Http::UploadedFile.new(tempfile: tempfile, filename: "test.tt")
|
42
|
+
res = storage.upload(file)
|
43
|
+
expect(res[:status]).to be_truthy
|
44
|
+
expect(File.extname(res[:result][:path])).to eq(".tt")
|
33
45
|
end
|
34
46
|
|
35
47
|
describe "upload file test " do
|
@@ -64,11 +76,11 @@ describe Fastdfs::Client::Storage do
|
|
64
76
|
end
|
65
77
|
|
66
78
|
it "can set metadata" do
|
67
|
-
expect(storage.set_metadata(TestConfig::
|
79
|
+
expect(storage.set_metadata(TestConfig::FILE_PATH, TestConfig::GROUP_NAME, TestConfig::METADATA)).to be_truthy
|
68
80
|
end
|
69
81
|
|
70
82
|
it "download the file to the local" do
|
71
|
-
res = storage.download(TestConfig::
|
83
|
+
res = storage.download(TestConfig::FILE_PATH, TestConfig::GROUP_NAME)
|
72
84
|
expect(res[:status]).to be_truthy
|
73
85
|
expect(res[:result]).to be_an_instance_of(Tempfile)
|
74
86
|
expect(IO.read(res[:result])).to eq(IO.read(TestConfig::FILE))
|
data/spec/test_config.rb
CHANGED
data/spec/tracker_spec.rb
CHANGED
@@ -43,7 +43,7 @@ describe Fastdfs::Client::Tracker do
|
|
43
43
|
res = storage.upload(File.open(File.expand_path("../page.png", __FILE__)))
|
44
44
|
expect(res[:status]).to be_truthy
|
45
45
|
results = res[:result]
|
46
|
-
|
46
|
+
res = storage.delete(results[:path], results[:group_name])
|
47
47
|
expect(res[:status]).to be_truthy
|
48
48
|
end
|
49
49
|
end
|
data/spec/upload.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
module ActionDispatch
|
2
|
+
module Http
|
3
|
+
|
4
|
+
class UploadedFile
|
5
|
+
attr_accessor :original_filename
|
6
|
+
|
7
|
+
attr_accessor :content_type
|
8
|
+
|
9
|
+
attr_accessor :tempfile
|
10
|
+
alias :to_io :tempfile
|
11
|
+
|
12
|
+
attr_accessor :headers
|
13
|
+
|
14
|
+
def initialize(hash)
|
15
|
+
@tempfile = hash[:tempfile]
|
16
|
+
raise(ArgumentError, ":tempfile is required") unless @tempfile
|
17
|
+
|
18
|
+
@original_filename = hash[:filename]
|
19
|
+
if @original_filename
|
20
|
+
begin
|
21
|
+
@original_filename.encode!(Encoding::UTF_8)
|
22
|
+
rescue EncodingError
|
23
|
+
@original_filename.force_encoding(Encoding::UTF_8)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
@content_type = hash[:type]
|
27
|
+
@headers = hash[:head]
|
28
|
+
end
|
29
|
+
|
30
|
+
def read(length=nil, buffer=nil)
|
31
|
+
@tempfile.read(length, buffer)
|
32
|
+
end
|
33
|
+
|
34
|
+
def open
|
35
|
+
@tempfile.open
|
36
|
+
end
|
37
|
+
|
38
|
+
def close(unlink_now=false)
|
39
|
+
@tempfile.close(unlink_now)
|
40
|
+
end
|
41
|
+
|
42
|
+
def path
|
43
|
+
@tempfile.path
|
44
|
+
end
|
45
|
+
|
46
|
+
def rewind
|
47
|
+
@tempfile.rewind
|
48
|
+
end
|
49
|
+
|
50
|
+
def size
|
51
|
+
@tempfile.size
|
52
|
+
end
|
53
|
+
|
54
|
+
def eof?
|
55
|
+
@tempfile.eof?
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fastdfs-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ka Ka
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-10-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -81,6 +81,7 @@ files:
|
|
81
81
|
- spec/storage_spec.rb
|
82
82
|
- spec/test_config.rb
|
83
83
|
- spec/tracker_spec.rb
|
84
|
+
- spec/upload.rb
|
84
85
|
homepage: https://github.com/huxinghai1988/fastdfs-client-ruby.git
|
85
86
|
licenses:
|
86
87
|
- MIT
|
@@ -113,4 +114,5 @@ test_files:
|
|
113
114
|
- spec/storage_spec.rb
|
114
115
|
- spec/test_config.rb
|
115
116
|
- spec/tracker_spec.rb
|
117
|
+
- spec/upload.rb
|
116
118
|
has_rdoc:
|