rtfs 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,19 +1,30 @@
1
1
  RTFS
2
2
  ====
3
3
 
4
- RTFS is a Ruby Client for TFS.
4
+ RTFS is a Ruby Client of [TFS](http://code.taobao.org/project/view/366/).
5
5
 
6
- [About TFS](http://code.taobao.org/project/view/366/)
6
+ For TFS integration with CarrierWave, see
7
+ [carrierwave-tfs](http://github.com/huacnlee/carrierwave-tfs) for more
8
+ information.
7
9
 
8
- This is basicly library for TFS access, you can use [carrierwave-tfs](http://github.com/huacnlee/carrierwave-tfs) for Carrierwave.
9
10
 
10
11
  Requirements
11
12
  ------------
12
13
 
13
- * Linux System (TFS only success build in Linux system.)
14
- * TFS
14
+ * <del>Linux System (tfstool can only be built on Linux Systems).</del>
15
+ * <del>tfstool</del>
15
16
 
16
- INSTALL
17
+ 2013-03-14
18
+
19
+ These are no longer valid requirements. TFS now favors
20
+ [Web Service API](http://baike.corp.taobao.com/index.php/CS_RD/tfs/use_web_service),
21
+ which requires nothing but a decent REST client of the language you choose.
22
+
23
+ See the [official documentation](http://baike.corp.taobao.com/index.php/CS_RD/tfs)
24
+ for more information about APIs and service applications.
25
+
26
+
27
+ Install
17
28
  -------
18
29
 
19
30
  ```bash
@@ -23,16 +34,16 @@ $ gem install rtfs
23
34
  Configure
24
35
  ---------
25
36
 
26
- create this files before using.
37
+ or How to integrate into Rails app.
27
38
 
28
- config/tfs.yml
39
+ Create `tfs.yml` in your rails app's config directory. The content of it should
40
+ look like this:
29
41
 
30
42
  ```yaml
43
+ # config/tfs.yml
31
44
  defaults: &defaults
32
- host: '127.0.0.1:3100'
33
- # or use WebService
34
45
  host: 'http://127.0.0.1:3900'
35
- appkey: "......."
46
+ appkey: "myprecious"
36
47
 
37
48
  development:
38
49
  <<: *defaults
@@ -44,21 +55,24 @@ production:
44
55
  <<: *defaults
45
56
  ```
46
57
 
47
- config/initialize/tfs.rb
58
+ Create an initializer too. Call it `tfs.rb` or whatever filename you fancy:
59
+
48
60
 
49
61
  ```ruby
62
+ # config/initializers/tfs.rb
50
63
  require 'rtfs'
51
64
  tfs_config = YAML.load_file("#{Rails.root}/config/tfs.yml")[Rails.env]
52
65
  $tfs = RTFS::Client.tfs(tfs_config.merge({:ns_addr => tfs_config['host']}))
53
66
  ```
54
67
 
55
- :ns_addr include http:// tfs used webservice
68
+ Then `$tfs` will be available as a global object.
56
69
 
57
70
 
58
- Usage
59
- -----
71
+ Simple Usage
72
+ ------------
60
73
 
61
74
  ```ruby
75
+ # app/controllers/users_controller.rb
62
76
  class UsersController < ApplicationController
63
77
  def save
64
78
  @user = User.new
@@ -68,7 +82,7 @@ class UsersController < ApplicationController
68
82
  end
69
83
  end
70
84
 
71
-
85
+ # app/models/user.rb
72
86
  class User < ActiveRecord::Base
73
87
  def avatar_url
74
88
  server_id = self.id % 4 + 1
@@ -77,9 +91,47 @@ class User < ActiveRecord::Base
77
91
  end
78
92
  ```
79
93
 
80
- Put local file to TFS
94
+ Put local file into TFS server:
81
95
 
82
96
  ```bash
97
+ $ bundle exec rails c
83
98
  irb> $tfs.put("~/Downloads/a.jpg")
84
99
  T1Ub1XXeFBXXb1upjX
85
- RTFS
100
+ RTFS
101
+ ```
102
+
103
+
104
+ API
105
+ ---
106
+
107
+ ```ruby
108
+ # initialize client.
109
+ tfs = RTFS::Client.new(:ns_addr => 'http://127.0.0.1:3800',
110
+ :appkey => 'myprecious',
111
+ :basedir => Rails.root.join('public'))
112
+
113
+ # simply put file.
114
+ tfs.put('foo.jpg') # ==> T1Ub1XXeFBXXb1upjX
115
+
116
+ # stat file.
117
+ tfs.stat('T1Ub1XXeFBXXb1upjX')
118
+
119
+ # remove file.
120
+ tfs.rm('T1Ub1XXeFBXXb1upjX')
121
+
122
+ # put named file, keep that name in TFS.
123
+ tfs.save('foo.jpg') # ==> 133/7463/foo.jpg
124
+
125
+ # remove named file.
126
+ tfs.del('foo.jpg') # ==> true
127
+
128
+ # put files under public folder, and preserve its name.
129
+ # will prepend the basedir in front of the file path passed in.
130
+ tfs.save('jquery.js')
131
+ ```
132
+
133
+
134
+ Executabes?
135
+ -----------
136
+
137
+ RTFS will be available as a executable binary soon. Stay tuned...
@@ -10,13 +10,10 @@ def require_local(suffix)
10
10
  end
11
11
 
12
12
  require 'rubygems'
13
- require 'nice-ffi'
14
13
  require 'yaml'
15
14
 
16
15
  # require_local 'rtfs/wrapper.rb'
17
16
  require 'rtfs/client.rb'
18
- require 'rtfs/web_service.rb'
19
- require 'rtfs/tfstool.rb'
20
17
  require 'rtfs/meta.rb'
21
18
  require 'rtfs/version.rb'
22
19
 
@@ -1,21 +1,203 @@
1
1
  # coding: utf-8
2
2
  # Code for client
3
3
  # by nowa<nowazhu@gmail.com> 2011-07-23
4
+ require 'rest-client'
5
+ require 'open-uri'
6
+ require 'digest'
7
+ require 'json'
8
+
4
9
  module RTFS
5
10
 
6
11
  class Client
7
12
 
8
13
  # 参数:
9
- # :ns_addr TFS 服务器地址,如 127.0.0.1:3100
10
- # :tfstool_path tfstool 安装路径,默认 /home/admin/tfs/bin/tfstool
14
+ # :root TFS WebService Root 服务器地址,如 127.0.0.1:3100
11
15
  def self.tfs(options)
12
- return nil unless options
13
- if options[:ns_addr].include?("http://")
14
- return RTFS::WebService.new(options)
16
+ self.new(options) if options
17
+ end
18
+
19
+ attr_accessor :nameservers
20
+ attr_accessor :appkey
21
+ attr_accessor :uid
22
+
23
+ def initialize(options)
24
+ # 通过 ns_addr 的地址获取负载均衡的地址
25
+ @nameservers = open("#{options[:ns_addr]}/tfs.list").read.split("\n")
26
+ @appkey = options[:appkey]
27
+
28
+ @basedir = options[:basedir]
29
+ @uid = options[:uid]
30
+
31
+ if @uid.nil? && !@basedir.nil?
32
+ (Digest::MD5.hexdigest(@basedir).to_i(16) % 10000)
33
+ end
34
+ end
35
+
36
+ # 获取文件
37
+ def get(tfs_name)
38
+ http_get("/v1/#{appkey}/#{tfs_name}")
39
+ end
40
+
41
+ # 上传文件
42
+ # 参数:
43
+ # file_path 需要上传的文件路径
44
+ # :ext 扩展名,默认会取 file_path 的扩展名, 如: .jpg
45
+ # 返回值
46
+ # T1lpVcXftHXXaCwpjX
47
+ def put(path, options = {})
48
+ ext = options[:ext] || File.extname(path)
49
+ path = path.to_s
50
+ resp = http_post("/v1/#{appkey}",
51
+ File.open(path.start_with?('/') ? path : fpath(path)).read,
52
+ :params => {
53
+ :suffix => ext,
54
+ :simple_name => options[:simple_name] || 0
55
+ },
56
+ :accept => :json)
57
+
58
+ json = JSON.parse(resp)
59
+ json && json['TFS_FILE_NAME']
60
+ end
61
+
62
+ # 上传文件 并返回完整 url (only for Taobao)
63
+ def put_and_get_url(path, options = {})
64
+ ext = options[:ext] || File.extname(path)
65
+ path = path.to_s
66
+ tname = put(path, :ext => ext)
67
+
68
+ "http://img0#{rand(4)+1}.taobaocdn.com/tfscom/#{t}#{ext}" unless tname.nil?
69
+ end
70
+
71
+ # 删除文件, 不能带扩展名
72
+ def rm(tname, options = {})
73
+ resp = http_delete("/v1/#{appkey}/#{tname}", :params => options)
74
+
75
+ resp && resp.code == 200
76
+ end
77
+
78
+ # 文件信息查看, 不能带扩展名
79
+ def stat(tname, options = {})
80
+ resp = http_get("/v1/#{appkey}/metadata/#{tname}", :params => options)
81
+
82
+ if resp && resp.code == 200
83
+ JSON.parse(resp)
84
+ end
85
+ end
86
+
87
+ def save(path, options = {})
88
+ path = path.to_s
89
+
90
+ if finger(path)
91
+ del(path)
92
+ save(path)
93
+ elsif create(path)
94
+ write(path)
95
+ end
96
+ end
97
+
98
+ def create(path, options = {})
99
+ resp = http_post(furl(path), nil,
100
+ :params => {:recursive => 1})
101
+
102
+ resp && resp.code == 201
103
+ end
104
+
105
+ def write(path, options = {})
106
+ data = File.open(fpath(path)).read
107
+ return if data.length == 0
108
+ resp = http_put(furl(path), data,
109
+ :params => {:offset => 0})
110
+
111
+ if resp && resp.code == 200
112
+ [appid, fuid(path), path].join('/')
113
+ end
114
+ end
115
+
116
+ def del(path, options = {})
117
+ resp = http_delete(furl(path))
118
+
119
+ resp && resp.code == 200
120
+ end
121
+
122
+ def finger(path, options = {})
123
+ begin
124
+ resp = http_head(furl(path))
125
+
126
+ resp && resp.code == 200
127
+ rescue RestClient::ResourceNotFound
128
+ # this rescue is intended.
129
+ # the purpose is to return nil if the path fingered returned 404.
130
+ # hence there's nothing more to do.
131
+ end
132
+ end
133
+
134
+ def appid
135
+ return @appid unless @appid.nil?
136
+
137
+ resp = http_get("/v2/#{appkey}/appid")
138
+
139
+ if resp && resp.code == 200
140
+ @appid = JSON.parse(resp)['APP_ID']
141
+ end
142
+ end
143
+
144
+
145
+ private
146
+
147
+ def http_get(url, *args)
148
+ RestClient.get("#{nameserver}#{url}", *args)
149
+ end
150
+
151
+ def http_post(url, *args)
152
+ RestClient.post("#{nameserver}#{url}", *args)
153
+ end
154
+
155
+ def http_delete(url, *args)
156
+ RestClient.delete("#{nameserver}#{url}", *args)
157
+ end
158
+
159
+ def http_put(url, *args)
160
+ RestClient.put("#{nameserver}#{url}", *args)
161
+ end
162
+
163
+ def http_head(url, *args)
164
+ RestClient.head("#{nameserver}#{url}", *args)
165
+ end
166
+
167
+ # 随机取一个 nameserver 用于访问,tfs.list 内容如下:
168
+ #
169
+ # 50
170
+ # 10.246.65.133:3900
171
+ # 10.246.65.132:3900
172
+ # 10.246.65.131:3900
173
+ # 10.246.65.130:3900
174
+ # 10.246.73.70:3900
175
+ # 10.246.73.71:3900
176
+ # 10.246.73.72:3900
177
+ #
178
+ def nameserver
179
+ # 现在第一行是 50,表示频次,访问 50 次就要更新
180
+ @nameservers[rand(@nameservers.size - 1) + 1]
181
+ end
182
+
183
+ # TFS 中需要这个 User ID,用来分散数据请求,减轻单台机器压力,最方便 uid 获取方式是,
184
+ # 对传入的文件路径做哈希,取后几位。但是如果要把 TFS 当普通 CDN 使用,
185
+ # 能够使用确定的 URL 更新文件的话,User ID 必须固定,只能不定期批量更新。
186
+ # 因此这里也允许使用实例化时传入的 uid 参数。
187
+ def fuid(path = nil)
188
+ if @uid.nil? && path.nil?
189
+ 1
15
190
  else
16
- return RTFS::Tfstool.new(options)
191
+ @uid || Digest::MD5.hexdigest(path).to_i(16) % 10000
17
192
  end
18
193
  end
19
194
 
195
+ def furl(path)
196
+ "/v2/#{appkey}/#{appid}/#{fuid(path)}/file/#{path}"
197
+ end
198
+
199
+ def fpath(path)
200
+ @basedir ? File.join(@basedir, path) : path
201
+ end
20
202
  end
21
203
  end
@@ -4,8 +4,8 @@
4
4
 
5
5
  module RTFS::Version
6
6
  MAJOR = 0
7
- MINOR = 1
8
- REVISION = 2
7
+ MINOR = 2
8
+ REVISION = 0
9
9
 
10
10
  class << self
11
11
  # Returns X.Y.Z formatted version string
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ require 'open-uri'
3
+
4
+ describe 'Basic operations' do
5
+ it 'should put and remove file' do
6
+ fname = $tfs.put('spec/a.jpg')
7
+
8
+ f = open("http://img01.daily.taobaocdn.net/tfscom/#{fname}.jpg")
9
+ f.read.length.should eq(6511)
10
+
11
+ $tfs.rm(fname).should eq(true)
12
+ end
13
+
14
+ it 'should stat file' do
15
+ fname = $tfs.put('spec/a.jpg')
16
+ stat = $tfs.stat(fname)
17
+
18
+ stat.should.is_a? Hash
19
+ stat['FILE_NAME'].should eq(fname)
20
+ stat['SIZE'].should eq(6511)
21
+
22
+ $tfs.rm(fname)
23
+ end
24
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+ require 'open-uri'
3
+
4
+ describe 'custom operations' do
5
+ it 'should save named file' do
6
+ path = $tfs.save('spec/a.jpg')
7
+
8
+ f = open("http://img01.daily.taobaocdn.net/L1/#{path}")
9
+ f.read.length.should eq(6511)
10
+
11
+ $tfs.del('spec/a.jpg').should eq(true)
12
+ end
13
+
14
+ it 'should expose appid' do
15
+ $tfs.appid.should eq('133')
16
+ end
17
+
18
+ it 'should respect global uid settings' do
19
+ # 自动生成的 uid 是经过 % 10000 的,也就是说,不会超过 10000,
20
+ # 所以,自定义 uid 只要大于等于 10000,就尽管用吧
21
+ $tfs.uid = 10000
22
+ path = $tfs.save('spec/a.jpg')
23
+
24
+ path.should =~ /10000/
25
+
26
+ # $tfs.del('spec/a.jpg').should eq(true)
27
+ end
28
+ end
@@ -1,3 +1,8 @@
1
1
  require "rtfs"
2
2
 
3
- $tfs = RTFS::Client.tfs(:ns_addr => "http://10.232.4.44:3800", :appkey => '4f8fbb734d4d8')
3
+ RSpec.configure do |config|
4
+ config.color = true
5
+ end
6
+
7
+ $tfs = RTFS::Client.tfs(:ns_addr => 'http://10.232.4.44:3800',
8
+ :appkey => '4f8fbb734d4d8')
metadata CHANGED
@@ -1,26 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rtfs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Nowa Zhu
9
9
  - Jason Lee
10
10
  - Cricy
11
+ - Jake Chen
11
12
  autorequire:
12
13
  bindir: bin
13
14
  cert_chain: []
14
- date: 2012-11-23 00:00:00.000000000 Z
15
+ date: 2013-03-15 00:00:00.000000000 Z
15
16
  dependencies:
16
17
  - !ruby/object:Gem::Dependency
17
- name: nice-ffi
18
+ name: rest-client
18
19
  requirement: !ruby/object:Gem::Requirement
19
20
  none: false
20
21
  requirements:
21
22
  - - ! '>='
22
23
  - !ruby/object:Gem::Version
23
- version: '0.4'
24
+ version: 1.6.0
24
25
  type: :runtime
25
26
  prerelease: false
26
27
  version_requirements: !ruby/object:Gem::Requirement
@@ -28,7 +29,23 @@ dependencies:
28
29
  requirements:
29
30
  - - ! '>='
30
31
  - !ruby/object:Gem::Version
31
- version: '0.4'
32
+ version: 1.6.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: json
35
+ requirement: !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ type: :development
42
+ prerelease: false
43
+ version_requirements: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
32
49
  - !ruby/object:Gem::Dependency
33
50
  name: rest-client
34
51
  requirement: !ruby/object:Gem::Requirement
@@ -37,7 +54,7 @@ dependencies:
37
54
  - - ! '>='
38
55
  - !ruby/object:Gem::Version
39
56
  version: 1.6.0
40
- type: :runtime
57
+ type: :development
41
58
  prerelease: false
42
59
  version_requirements: !ruby/object:Gem::Requirement
43
60
  none: false
@@ -45,11 +62,28 @@ dependencies:
45
62
  - - ! '>='
46
63
  - !ruby/object:Gem::Version
47
64
  version: 1.6.0
65
+ - !ruby/object:Gem::Dependency
66
+ name: rspec
67
+ requirement: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ~>
71
+ - !ruby/object:Gem::Version
72
+ version: '2.5'
73
+ type: :development
74
+ prerelease: false
75
+ version_requirements: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ~>
79
+ - !ruby/object:Gem::Version
80
+ version: '2.5'
48
81
  description:
49
82
  email:
50
83
  - nowazhu@gmail.com
51
84
  - huacnlee@gmail.com
52
85
  - feiyelanghai@gmail.com
86
+ - jakeplus@gmail.com
53
87
  executables: []
54
88
  extensions: []
55
89
  extra_rdoc_files:
@@ -57,24 +91,19 @@ extra_rdoc_files:
57
91
  - CHANGES.md
58
92
  - MIT-LICENSE
59
93
  files:
60
- - .gitignore
61
- - CHANGES.md
62
- - MIT-LICENSE
63
- - README.md
64
- - lib/rtfs.rb
65
94
  - lib/rtfs/client.rb
66
95
  - lib/rtfs/meta.rb
67
- - lib/rtfs/tfstool.rb
68
96
  - lib/rtfs/version.rb
69
- - lib/rtfs/web_service.rb
70
- - lib/rtfs/wrapper.rb
71
- - rtfs.gemspec
72
- - spec/a.jpg
73
- - spec/b.jpg
97
+ - lib/rtfs.rb
98
+ - README.md
99
+ - CHANGES.md
100
+ - MIT-LICENSE
101
+ - spec/basics_spec.rb
102
+ - spec/custom_spec.rb
74
103
  - spec/spec_helper.rb
75
- - spec/upload_spec.rb
76
104
  homepage: https://github.com/nowa/rtfs
77
- licenses: []
105
+ licenses:
106
+ - MIT
78
107
  post_install_message:
79
108
  rdoc_options: []
80
109
  require_paths:
@@ -98,7 +127,6 @@ signing_key:
98
127
  specification_version: 3
99
128
  summary: RTFS is a Ruby Client for TFS.
100
129
  test_files:
101
- - spec/a.jpg
102
- - spec/b.jpg
130
+ - spec/basics_spec.rb
131
+ - spec/custom_spec.rb
103
132
  - spec/spec_helper.rb
104
- - spec/upload_spec.rb
data/.gitignore DELETED
@@ -1,3 +0,0 @@
1
- pkg/*
2
- .DS_Store
3
- *.gem
@@ -1,89 +0,0 @@
1
- # coding: utf-8
2
- module RTFS
3
-
4
- TFSTOOL_PATH = "/home/admin/tfs/bin/tfstool"
5
- class Tfstool
6
-
7
- attr_accessor :ns_addr
8
- attr_accessor :tfstool_path
9
-
10
- # 参数:
11
- # :ns_addr TFS 服务器地址,如 127.0.0.1:3100
12
- # :tfstool_path tfstool 安装路径,默认 /home/admin/tfs/bin/tfstool
13
- def initialize(options)
14
- return nil unless options
15
- @ns_addr = options[:ns_addr]
16
- @tfstool_path = options[:tfstool_path] ? options[:tfstool_path] : TFSTOOL_PATH
17
- if not File.exist?(@tfstool_path)
18
- puts "[RTFS] debuger: #{@tfstool_path}"
19
- raise NoTFSToolError.new
20
- end
21
- end
22
-
23
- # 获取文件
24
- def get(tfs_name, local_file=nil)
25
- local_file ||= tfs_name
26
- `#{tfstool_cmd} -i "get #{tfs_name} #{local_file}"`
27
- end
28
-
29
- # 上传文件
30
- # 参数:
31
- # file_path 需要上传的文件路径
32
- # :ext 扩展名,默认会取 file_path 的扩展名, 如: .jpg
33
- # 返回值
34
- # T1lpVcXftHXXaCwpjX
35
- def put(file_path, options = {})
36
- ext = options[:ext] || File.extname(file_path)
37
- tfs_name = "NULL"
38
- result = `#{tfstool_cmd} -i "put #{file_path} #{tfs_name} #{ext}"`
39
- # puts "result: #{result}"
40
- t = nil
41
- if result.include?("=> ")
42
- result = result.split("=> ").last
43
- if result.include?(",")
44
- t = result.split(",").first
45
- end
46
- end
47
- t.nil? ? nil : t
48
- end
49
-
50
- # 上传文件 并返回完整 url (only for Taobao)
51
- def put_and_get_url(file_path, options = {})
52
- ext = options[:ext] || File.extname(file_path)
53
- t = put(file_path, :ext => ext)
54
- t.nil? ? nil : "http://img03.taobaocdn.com/tfscom/#{t}#{ext}"
55
- end
56
-
57
- # 删除文件, 不能带扩展名
58
- def rm(tfs_name)
59
- `#{tfstool_cmd} -i "rm #{tfs_name}"`
60
- end
61
-
62
- # 改名, 不能带扩展名
63
- def rename(tfs_name, new_name)
64
- `#{tfstool_cmd} -i "rename #{tfs_name} #{new_name}"`
65
- end
66
-
67
- # 文件信息查看, 不能带扩展名
68
- def stat(tfs_name)
69
- result = `#{tfstool_cmd} -i "stat #{tfs_name}"`
70
- stat = {}
71
- result.split("\n").each do |line|
72
- line = line.split(':').map {|i| i.gsub!(" ", "")}
73
- stat["#{line.first}"] = line.last
74
- end
75
- stat
76
- end
77
-
78
- protected
79
- def tfstool_cmd
80
- "#{@tfstool_path} -n -s #{@ns_addr}"
81
- end
82
- end
83
-
84
- class NoTFSToolError < RuntimeError
85
- def to_s
86
- "You must install tfs from yum or source first!"
87
- end
88
- end # NoTFSToolError
89
- end
@@ -1,96 +0,0 @@
1
- # coding: utf-8
2
- require 'rest-client'
3
- require 'open-uri'
4
- require "json"
5
-
6
- module RTFS
7
- class WebService
8
-
9
- attr_accessor :appkey
10
- attr_accessor :ns_addrs
11
-
12
- def initialize(options)
13
- return nil unless options
14
- # 通过 ns_addr 的地址获取负载均衡的地址
15
- @ns_addrs ||= open("#{options[:ns_addr]}/tfs.list").read.split("\n")
16
- @appkey = options[:appkey]
17
- end
18
-
19
- # 随机取一个 ns_addr 用于访问
20
- # 50
21
- # 10.246.65.133:3900
22
- # 10.246.65.132:3900
23
- # 10.246.65.131:3900
24
- # 10.246.65.130:3900
25
- # 10.246.73.70:3900
26
- # 10.246.73.71:3900
27
- # 10.246.73.72:3900
28
- def ns_addr
29
-
30
- #现在第一行是50,表示频次,访问50次就要更新
31
- @ns_addrs[rand(@ns_addrs.size - 1) + 1]
32
- end
33
-
34
- # 获取文件
35
- def get(tfs_name, local_file=nil)
36
- RestClient.get(get_url("/v1/#{appkey}/#{tfs_name}"))
37
- end
38
-
39
- # 上传文件
40
- # 参数:
41
- # file_path 需要上传的文件路径
42
- # :ext 扩展名,默认会取 file_path 的扩展名, 如: .jpg
43
- # 返回值
44
- # T1lpVcXftHXXaCwpjX
45
- def put(file_path, options = {})
46
- ext = options[:ext] || File.extname(file_path)
47
- response = RestClient.post(get_url("/v1/#{appkey}",{:suffix => ext, :simple_name => options[:simple_name] || 0}),File.open(file_path).read, :accept => :json )
48
- json = JSON.parse(response)
49
- json && json["TFS_FILE_NAME"] ? json["TFS_FILE_NAME"] : nil
50
- end
51
-
52
- # 上传文件 并返回完整 url (only for Taobao)
53
- def put_and_get_url(file_path, options = {})
54
- ext = options[:ext] || File.extname(file_path)
55
- t = put(file_path, :ext => ext)
56
- t.nil? ? nil : "http://img0#{rand(4)+1}.taobaocdn.com/tfscom/#{t}#{ext}"
57
- end
58
-
59
- # 删除文件, 不能带扩展名
60
- def rm(tfs_name,options = {})
61
- response = RestClient.delete(get_url("/v1/#{appkey}/#{tfs_name}", options))
62
- response && response.code == 200 ? true : nil
63
- end
64
-
65
- # 改名, 不能带扩展名
66
- def rename(tfs_name, new_name)
67
- #`#{tfstool_cmd} -i "rename #{tfs_name} #{new_name}"`
68
- end
69
-
70
- # 文件信息查看, 不能带扩展名
71
- def stat(tfs_name,options = {})
72
- response = RestClient.get(get_url("/v1/#{appkey}/metadata/#{tfs_name}", options))
73
- response && response.code == 200 ? JSON.parse(response) : nil
74
- end
75
-
76
- def client_name
77
- "WebService"
78
- end
79
-
80
- private
81
-
82
- def appkey
83
- @appkey
84
- end
85
-
86
- def get_url(url,opts = {})
87
- return url unless opts
88
- url = "#{self.ns_addr}#{url}"
89
- params = []
90
- opts.each{ |k,v|
91
- params << "#{k}=#{v}"
92
- }
93
- url.include?("?") ? "#{url}&#{params.join("&")}" : "#{url}?#{params.join("&")}"
94
- end
95
- end
96
- end
@@ -1,68 +0,0 @@
1
- # coding: utf-8
2
- # 使用ffi和nice-ffi来调用动态库的c接口
3
- # tfsclient c api目前尚不完善,基于c接口的封装调用不能满足需求
4
- # 因此目前不使用该wrapper,文件暂存
5
- # by nowa<nowazhu@gmail.com> 2011-07-23
6
-
7
- module LibC
8
- extend FFI::Library
9
- # figures out the correct libc for each platform including Windows
10
- library = ffi_lib(FFI::Library::LIBC).first
11
-
12
- # Size_t not working properly on Windows
13
- find_type(:size_t) rescue typedef(:ulong, :size_t)
14
-
15
- # memory allocators
16
- attach_function :malloc, [:size_t], :pointer
17
- attach_function :free, [:pointer], :void
18
-
19
- # get a pointer to the free function; used for ZMQ::Message deallocation
20
- Free = library.find_symbol('free')
21
-
22
- # memory movers
23
- attach_function :memcpy, [:pointer, :pointer, :size_t], :pointer
24
- end # module LibC
25
-
26
- module LibRTFS
27
- extend NiceFFI::Library
28
-
29
- libs_dir = "/home/admin/tfs/lib/"
30
- pathset = NiceFFI::PathSet::DEFAULT.prepend(libs_dir)
31
-
32
- load_library("tfsclient_c", pathset)
33
-
34
- attach_function :t_initialize, [:string, :int, :int], :int
35
-
36
- #enum OpenFlag
37
- # {
38
- # T_READ = 1,
39
- # T_WRITE = 2,
40
- # T_CREATE = 4,
41
- # T_NEWBLK = 8,
42
- # T_NOLEASE = 16,
43
- # T_STAT = 32,
44
- # T_LARGE = 64
45
- # };
46
- attach_function :t_open, [:string, :string, :string, :int, :string], :int
47
- attach_function :t_read, [:int, :pointer, :int], :int
48
- attach_function :t_write, [:int, :pointer, :int], :int
49
- attach_function :t_lseek, [:int, :int, :int], :int
50
- attach_function :t_pread, [:int, :pointer, :int, :int], :int
51
- attach_function :t_pwrite, [:int, :pointer, :int, :int], :int
52
- attach_function :t_fstat, [:int, :pointer, :int], :int
53
- attach_function :t_close, [:int, :string, :int], :int
54
- attach_function :t_unlink, [:string, :string, :int], :int
55
- end
56
-
57
- # 下面这部分代码仅供测试LibRTFS
58
- # LibRTFS.t_initialize("10.232.35.32:3100", 5, 1000)
59
- # fd = LibRTFS.t_open("test", ".png", nil, 2, nil)
60
- # puts "fd: #{fd}"
61
- #
62
- # ori_file = nil
63
- # File.open("/home/xifeng/1.png", "r") do |f|
64
- # ori_file = f.read
65
- # end
66
- # buffer = LibC.malloc ori_file.size
67
- # buffer.write_string ori_file, ori_file.size
68
- # puts "write: #{LibRTFS.t_write(fd, buffer, ori_file.size)}"
@@ -1,19 +0,0 @@
1
- # coding: utf-8
2
- Gem::Specification.new do |s|
3
- s.name = "rtfs"
4
- s.version = "0.1.2"
5
- s.platform = Gem::Platform::RUBY
6
- s.has_rdoc = true
7
- s.extra_rdoc_files = ["README.md","CHANGES.md","MIT-LICENSE",]
8
- s.summary = "RTFS is a Ruby Client for TFS."
9
- s.author = ["Nowa Zhu","Jason Lee","Cricy"]
10
- s.email = ["nowazhu@gmail.com","huacnlee@gmail.com","feiyelanghai@gmail.com"]
11
- s.homepage = "https://github.com/nowa/rtfs"
12
- s.files = `git ls-files`.split("\n")
13
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
- s.require_paths = ["lib"]
15
- s.bindir = 'bin'
16
-
17
- s.add_dependency("nice-ffi", ">=0.4")
18
- s.add_dependency("rest-client", ">=1.6.0")
19
- end
data/spec/a.jpg DELETED
Binary file
data/spec/b.jpg DELETED
Binary file
@@ -1,14 +0,0 @@
1
- require "spec_helper"
2
- require "open-uri"
3
-
4
- describe "Base upload" do
5
- it "should upload" do
6
- fname = $tfs.put("spec/a.jpg")
7
- f = open("http://10.232.4.42/tfscom/#{fname}.jpg")
8
- f.read.length.should == 6153
9
-
10
- fname = $tfs.put("spec/b.jpg")
11
- f = open("http://10.232.4.42/tfscom/#{fname}.jpg")
12
- f.read.length.should == 114504
13
- end
14
- end