slipsquare 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.travis.yml +9 -0
- data/CHANGELOG.md +21 -0
- data/CONTRIBUTING.md +28 -0
- data/Gemfile +4 -0
- data/LICENSE.md +22 -0
- data/README.md +93 -0
- data/Rakefile +6 -0
- data/bin/slipsquare +7 -0
- data/lib/slipsquare.rb +6 -0
- data/lib/slipsquare/cli.rb +105 -0
- data/lib/slipsquare/config.rb +67 -0
- data/lib/slipsquare/middleware.rb +106 -0
- data/lib/slipsquare/middleware/account.rb +14 -0
- data/lib/slipsquare/middleware/ask_for_credentials.rb +39 -0
- data/lib/slipsquare/middleware/base.rb +28 -0
- data/lib/slipsquare/middleware/check_configuration.rb +18 -0
- data/lib/slipsquare/middleware/check_credentials.rb +27 -0
- data/lib/slipsquare/middleware/chunked_upload.rb +29 -0
- data/lib/slipsquare/middleware/delete_file.rb +13 -0
- data/lib/slipsquare/middleware/download_file.rb +25 -0
- data/lib/slipsquare/middleware/inject_client.rb +27 -0
- data/lib/slipsquare/middleware/inject_configuration.rb +15 -0
- data/lib/slipsquare/middleware/list_files.rb +19 -0
- data/lib/slipsquare/middleware/make_directory.rb +25 -0
- data/lib/slipsquare/middleware/upload_file.rb +17 -0
- data/lib/slipsquare/version.rb +3 -0
- data/slipsquare.gemspec +34 -0
- data/spec/cli/account.rb +24 -0
- data/spec/cli/authorize_spec.rb +46 -0
- data/spec/cli/chunked_upload_spec.rb +39 -0
- data/spec/cli/delete_file.rb +23 -0
- data/spec/cli/download_file.rb +43 -0
- data/spec/cli/get_keys_spec.rb +30 -0
- data/spec/cli/help_cli_spec.rb +17 -0
- data/spec/cli/ls_spec.rb +36 -0
- data/spec/cli/mkdir_spec.rb +52 -0
- data/spec/cli/upload_file.rb +33 -0
- data/spec/cli/verify_spec.rb +33 -0
- data/spec/cli/version_cli_spec.rb +16 -0
- data/spec/config_spec.rb +70 -0
- data/spec/fixtures/account.json +11 -0
- data/spec/fixtures/chunked_upload.json +5 -0
- data/spec/fixtures/commit_chunked_upload.json +13 -0
- data/spec/fixtures/find_foo_directory.json +15 -0
- data/spec/fixtures/ls_path_success.json +29 -0
- data/spec/fixtures/ls_success.json +14 -0
- data/spec/fixtures/mkdir_success.json +12 -0
- data/spec/fixtures/mkdir_success_multiple_path.json +12 -0
- data/spec/fixtures/upload_success.json +13 -0
- data/spec/fixtures/verify_success.json +14 -0
- data/spec/middleware/base_spec.rb +15 -0
- data/spec/middleware/check_configuration_spec.rb +16 -0
- data/spec/middleware/inject_configuration_spec.rb +16 -0
- data/spec/shared/environment.rb +49 -0
- data/spec/spec_helper.rb +20 -0
- data/tmp/.gitkeep +0 -0
- metadata +270 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
require "dropbox-api"
|
2
|
+
require "cgi"
|
3
|
+
|
4
|
+
module Slipsquare
|
5
|
+
module Middleware
|
6
|
+
# Ask for user credentials from the command line, then write them out.
|
7
|
+
class AskForCredentials < Base
|
8
|
+
def call(env)
|
9
|
+
|
10
|
+
say "If you dont know your app and secret key, try `slipsquare get-keys`"
|
11
|
+
|
12
|
+
app_key = ask "Enter your App key:"
|
13
|
+
secret_key = ask "Enter your Secret key:"
|
14
|
+
|
15
|
+
Dropbox::API::Config.app_key = app_key
|
16
|
+
Dropbox::API::Config.app_secret = secret_key
|
17
|
+
|
18
|
+
consumer = Dropbox::API::OAuth.consumer(:authorize)
|
19
|
+
request_token = consumer.get_request_token
|
20
|
+
say "Go to this url and click 'Authorize' to get the token:"
|
21
|
+
say request_token.authorize_url, :green
|
22
|
+
query = request_token.authorize_url.split('?').last
|
23
|
+
params = CGI.parse(query)
|
24
|
+
token = params['oauth_token'].first
|
25
|
+
yes? "Once you authorize the app on Dropbox, type yes... "
|
26
|
+
access_token = request_token.get_access_token(:oauth_verifier => token)
|
27
|
+
|
28
|
+
# Write the config file.
|
29
|
+
env['config'].create_config_file(app_key, secret_key, access_token.token, access_token.secret)
|
30
|
+
env['config'].reload!
|
31
|
+
|
32
|
+
say "Credentials saved to ~/.slipsquare"
|
33
|
+
|
34
|
+
@app.call(env)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Slipsquare
|
2
|
+
module Middleware
|
3
|
+
# A base middleware class to initalize.
|
4
|
+
class Base
|
5
|
+
# Some colors for making things pretty.
|
6
|
+
CLEAR = "\e[0m"
|
7
|
+
RED = "\e[31m"
|
8
|
+
GREEN = "\e[32m"
|
9
|
+
YELLOW = "\e[33m"
|
10
|
+
|
11
|
+
# We want access to all of the fun thor cli helper methods,
|
12
|
+
# like say, yes?, ask, etc.
|
13
|
+
include Thor::Shell
|
14
|
+
|
15
|
+
def initialize(app)
|
16
|
+
@app = app
|
17
|
+
# This resets the color to "clear" on the user's terminal.
|
18
|
+
say "", :clear, false
|
19
|
+
end
|
20
|
+
|
21
|
+
def call(env)
|
22
|
+
@app.call(env)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Slipsquare
|
2
|
+
module Middleware
|
3
|
+
# Check if the client has set-up configuration yet.
|
4
|
+
class CheckConfiguration < Base
|
5
|
+
def call(env)
|
6
|
+
config = env["config"]
|
7
|
+
|
8
|
+
if !config || !config.data || !config.app_key || !config.secret_key
|
9
|
+
say "You must run `slipsquare authorize` in order to connect to Dropbox", :red
|
10
|
+
exit 1
|
11
|
+
end
|
12
|
+
|
13
|
+
@app.call(env)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'dropbox-api'
|
3
|
+
require 'cgi'
|
4
|
+
|
5
|
+
module Slipsquare
|
6
|
+
module Middleware
|
7
|
+
class CheckCredentials < Base
|
8
|
+
def call(env)
|
9
|
+
|
10
|
+
say "Checking credentials with Dropbox..."
|
11
|
+
|
12
|
+
begin
|
13
|
+
env['dropbox-client'].ls
|
14
|
+
rescue Dropbox::API::Error => e
|
15
|
+
say "Connection to Dropbox failed (#{e})", :red
|
16
|
+
say "Check your .slipsquare file, and double check your credentials are correct", :yellow
|
17
|
+
exit 1
|
18
|
+
end
|
19
|
+
|
20
|
+
say "Connection to dropbox successful!", :green
|
21
|
+
|
22
|
+
@app.call(env)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'ruby-progressbar'
|
2
|
+
|
3
|
+
module Slipsquare
|
4
|
+
module Middleware
|
5
|
+
class ChunkedUpload < Base
|
6
|
+
def call(env)
|
7
|
+
say "Starting chunked upload"
|
8
|
+
|
9
|
+
file_name = env['chunked_upload_file_name']
|
10
|
+
contents = File.open(env['chunked_upload_file_name'])
|
11
|
+
total_size = File.size(env['chunked_upload_file_name'])
|
12
|
+
|
13
|
+
say "Total Size: #{total_size} bytes"
|
14
|
+
upload_progress_bar = ProgressBar.create(:title => "Upload progress",
|
15
|
+
:format => '%a <%B> %p%% %t',
|
16
|
+
:starting_at => 0,
|
17
|
+
:total => total_size)
|
18
|
+
|
19
|
+
response = env['dropbox-client'].chunked_upload file_name, contents do |offset, upload|
|
20
|
+
upload_progress_bar.progress += offset
|
21
|
+
end
|
22
|
+
|
23
|
+
say "File uploaded successfully!"
|
24
|
+
|
25
|
+
@app.call(env)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Slipsquare
|
2
|
+
module Middleware
|
3
|
+
class DownloadFile < Base
|
4
|
+
def call(env)
|
5
|
+
say "Download file..."
|
6
|
+
|
7
|
+
begin
|
8
|
+
contents = env['dropbox-client'].download env['download_file_name']
|
9
|
+
rescue Dropbox::API::Error::NotFound => e
|
10
|
+
say "File Not Found! Could not download", :red
|
11
|
+
exit 1
|
12
|
+
rescue Dropbox::API::Error => e
|
13
|
+
say "Connection to Dropbox failed (#{e})", :red
|
14
|
+
exit 1
|
15
|
+
end
|
16
|
+
|
17
|
+
File.open(env['download_file_name'], 'w') {|f| f.write(contents) }
|
18
|
+
|
19
|
+
say "File '#{env['download_file_name']}' downloaded successfully!"
|
20
|
+
|
21
|
+
@app.call(env)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require "dropbox-api"
|
3
|
+
|
4
|
+
module Slipsquare
|
5
|
+
module Middleware
|
6
|
+
class InjectClient < Base
|
7
|
+
def call(env)
|
8
|
+
|
9
|
+
Dropbox::API::Config.app_key = env['config'].app_key
|
10
|
+
Dropbox::API::Config.app_secret = env['config'].secret_key
|
11
|
+
Dropbox::API::Config.mode = 'dropbox'
|
12
|
+
|
13
|
+
begin
|
14
|
+
client = Dropbox::API::Client.new(:token => env['config'].app_token, :secret => env['config'].app_secret)
|
15
|
+
rescue Dropbox::API::Error => e
|
16
|
+
say "Connection to Dropbox failed (#{e})", :red
|
17
|
+
exit 1
|
18
|
+
end
|
19
|
+
|
20
|
+
env['dropbox-client'] = client
|
21
|
+
|
22
|
+
@app.call(env)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Slipsquare
|
2
|
+
module Middleware
|
3
|
+
# Check if the client has set-up configuration yet.
|
4
|
+
class InjectConfiguration < Base
|
5
|
+
def call(env)
|
6
|
+
config = Slipsquare::Configuration.instance
|
7
|
+
|
8
|
+
env["config"] = config
|
9
|
+
|
10
|
+
@app.call(env)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'table_print'
|
2
|
+
|
3
|
+
module Slipsquare
|
4
|
+
module Middleware
|
5
|
+
class ListFiles < Base
|
6
|
+
def call(env)
|
7
|
+
say "Listing files from Dropbox..."
|
8
|
+
|
9
|
+
if env["list_files_path"].nil?
|
10
|
+
tp env['dropbox-client'].ls, 'path', 'mime_type', 'size'
|
11
|
+
else
|
12
|
+
tp env['dropbox-client'].ls(env["list_files_path"]), 'path', 'mime_type', 'size'
|
13
|
+
end
|
14
|
+
|
15
|
+
@app.call(env)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'table_print'
|
2
|
+
|
3
|
+
module Slipsquare
|
4
|
+
module Middleware
|
5
|
+
class MakeDirectory < Base
|
6
|
+
def call(env)
|
7
|
+
say "Creating directory on Dropbox..."
|
8
|
+
|
9
|
+
friendly_path = env["mkdir_path"]
|
10
|
+
|
11
|
+
if friendly_path =~ (/[\\\:\?\*\<\>\"\|]+/)
|
12
|
+
friendly_path = friendly_path.gsub(/[\\\:\?\*\<\>\"\|]+/, '')
|
13
|
+
say "Illegal character found! Escaping...", :yellow
|
14
|
+
say "Escaped directory path: #{friendly_path}"
|
15
|
+
end
|
16
|
+
|
17
|
+
new_folder_response = env['dropbox-client'].mkdir(env["mkdir_path"])
|
18
|
+
|
19
|
+
say "Directory `#{friendly_path}` created successfully", :green
|
20
|
+
|
21
|
+
@app.call(env)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Slipsquare
|
2
|
+
module Middleware
|
3
|
+
class UploadFile < Base
|
4
|
+
def call(env)
|
5
|
+
say "Uploading file..."
|
6
|
+
|
7
|
+
contents = File.read(env['upload_file_name'])
|
8
|
+
|
9
|
+
env['dropbox-client'].upload env['upload_file_name'], contents
|
10
|
+
|
11
|
+
say "File '#{env['upload_file_name']}' uploaded successfully"
|
12
|
+
|
13
|
+
@app.call(env)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/slipsquare.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'slipsquare/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "slipsquare"
|
8
|
+
gem.version = Slipsquare::VERSION
|
9
|
+
gem.authors = ["Peter Souter"]
|
10
|
+
gem.email = ["p.morsou@gmail.com"]
|
11
|
+
gem.description = %q{A command line tool for uploading to dropbox.}
|
12
|
+
gem.summary = %q{Slipsquare is a CLI for Dropbox, for downloading and uploading files.}
|
13
|
+
gem.homepage = "https://github.com/petems/slipsquare"
|
14
|
+
gem.license = 'MIT'
|
15
|
+
|
16
|
+
gem.files = `git ls-files`.split($/)
|
17
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
18
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
|
+
gem.require_paths = ["lib"]
|
20
|
+
|
21
|
+
gem.add_dependency "thor", "~> 0.18.1"
|
22
|
+
gem.add_dependency "middleware" , "~> 0.1.0"
|
23
|
+
|
24
|
+
gem.add_dependency "dropbox-api-petems", "0.4.2"
|
25
|
+
gem.add_dependency "table_print", "~> 1.1.5"
|
26
|
+
gem.add_dependency "ruby-progressbar", "~> 1.2.0"
|
27
|
+
|
28
|
+
gem.add_development_dependency "rake", "~> 10.1.0"
|
29
|
+
gem.add_development_dependency "rspec-core", "~> 2.13.0"
|
30
|
+
gem.add_development_dependency "rspec-expectations", "~> 2.13.0"
|
31
|
+
gem.add_development_dependency "rspec-mocks", "~> 2.13.0"
|
32
|
+
gem.add_development_dependency "webmock", "~> 1.11.0"
|
33
|
+
|
34
|
+
end
|
data/spec/cli/account.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Slipsquare::CLI do
|
4
|
+
include_context "spec"
|
5
|
+
|
6
|
+
describe "account" do
|
7
|
+
it "returns account info" do
|
8
|
+
|
9
|
+
stub_request(:get, "https://api.dropbox.com/1/account/info?").
|
10
|
+
with(:headers => {'Accept'=>'*/*', 'Authorization'=>/OAuth oauth_consumer_key="#{app_key}", oauth_nonce="\S+", oauth_signature="\S+", oauth_signature_method="HMAC-SHA1", oauth_timestamp="\S+", oauth_token="#{app_token}", oauth_version="1.0"/, 'User-Agent'=>'OAuth gem v0.4.7'}).
|
11
|
+
to_return(:status => 200, :body => fixture('account'))
|
12
|
+
|
13
|
+
@cli.account
|
14
|
+
expect($stdout.string).to eq <<-eos
|
15
|
+
REFERRAL_LINK | DISPLAY_NAME | UID | COUNTRY | QUOTA_INFO
|
16
|
+
-------------------------------|--------------|----------|---------|-------------------------------
|
17
|
+
https://www.dropbox.com/ref... | John P. User | 12345678 | US | #<Dropbox::API::Object norm...
|
18
|
+
eos
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Slipsquare::CLI do
|
4
|
+
include_context "spec"
|
5
|
+
|
6
|
+
describe "authorize" do
|
7
|
+
before do
|
8
|
+
stub_request(:post, "https://www.dropbox.com/1/oauth/request_token").
|
9
|
+
with(:headers => {'Accept'=>'*/*', 'Authorization'=>/OAuth oauth_body_hash="\S+", oauth_callback="oob", oauth_consumer_key="foo", oauth_nonce="\S+", oauth_signature="\S+", oauth_signature_method="HMAC-SHA1", oauth_timestamp="\S+", oauth_version="1.0"/, 'Content-Length'=>'0', 'User-Agent'=>'OAuth gem v0.4.7'}).
|
10
|
+
to_return(:status => 200, :body => "oauth_token_secret=b9q1n5il4lcc&oauth_token=mh7an9dkrg59")
|
11
|
+
|
12
|
+
stub_request(:post, "https://www.dropbox.com/1/oauth/access_token").
|
13
|
+
with(:headers => {'Accept'=>'*/*', 'Authorization'=>/OAuth oauth_body_hash="\S+", oauth_consumer_key="#{app_key}", oauth_nonce="\S+", oauth_signature="\S+", oauth_signature_method="HMAC-SHA1", oauth_timestamp="\S+", oauth_token="\S+", oauth_verifier="\S+", oauth_version="1.0"/, 'Content-Length'=>'0', 'User-Agent'=>'OAuth gem v0.4.7'}).
|
14
|
+
to_return(:status => 200, :body => "oauth_token_secret=95grkd9na7hm&oauth_token=ccl4li5n1q9b&uid=100")
|
15
|
+
|
16
|
+
stub_request(:get, "https://api.dropbox.com/1/metadata/dropbox/?").
|
17
|
+
with(:headers => {'Accept'=>'*/*', 'Authorization'=>/OAuth oauth_consumer_key="#{app_key}", oauth_nonce="\S+", oauth_signature="\S+", oauth_signature_method="HMAC-SHA1", oauth_timestamp="\S+", oauth_token="\S+", oauth_version="1.0"/, 'User-Agent'=>'OAuth gem v0.4.7'}).
|
18
|
+
to_return(:status => 200, :body => fixture("verify_success"))
|
19
|
+
end
|
20
|
+
|
21
|
+
it "asks the right questions and saves then checks credentials" do
|
22
|
+
|
23
|
+
$stdout.should_receive(:print).exactly(6).times
|
24
|
+
$stdout.should_receive(:print).with("Enter your App key: ")
|
25
|
+
$stdin.should_receive(:gets).and_return(app_key)
|
26
|
+
$stdout.should_receive(:print).with("Enter your Secret key: ")
|
27
|
+
$stdin.should_receive(:gets).and_return(secret_key)
|
28
|
+
$stdout.should_receive(:print).with("Once you authorize the app on Dropbox, type yes... ")
|
29
|
+
$stdin.should_receive(:gets).and_return('yes')
|
30
|
+
|
31
|
+
@cli.authorize
|
32
|
+
|
33
|
+
expect($stdout.string).to eq <<-eos
|
34
|
+
If you dont know your app and secret key, try `slipsquare get-keys`
|
35
|
+
Go to this url and click 'Authorize' to get the token:
|
36
|
+
https://www.dropbox.com/1/oauth/authorize?oauth_token=mh7an9dkrg59
|
37
|
+
Credentials saved to ~/.slipsquare
|
38
|
+
Checking credentials with Dropbox...
|
39
|
+
Connection to dropbox successful!
|
40
|
+
eos
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Slipsquare::CLI do
|
4
|
+
include_context "spec"
|
5
|
+
|
6
|
+
before :each do
|
7
|
+
File.open("foo.txt", 'w') {|f| f.write("Laugh and grow fat...") }
|
8
|
+
end
|
9
|
+
|
10
|
+
after :each do
|
11
|
+
File.delete("foo.txt") if File.exist?("foo.txt")
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "upload-chunked" do
|
15
|
+
|
16
|
+
it "uploads a larger file and gives progress" do
|
17
|
+
|
18
|
+
stub_request(:put, "https://api-content.dropbox.com/1/chunked_upload?offset=0").
|
19
|
+
with(:body => "Laugh and grow fat...",
|
20
|
+
:headers => {'Accept'=>'*/*', 'Authorization'=>/OAuth oauth_body_hash="\S+", oauth_consumer_key="#{app_key}", oauth_nonce="\S+", oauth_signature="\S+", oauth_signature_method="HMAC-SHA1", oauth_timestamp="\S+", oauth_token="#{app_token}", oauth_version="1.0"/, 'Content-Length'=>'21', 'Content-Type'=>'application/octet-stream', 'User-Agent'=>'OAuth gem v0.4.7'}).
|
21
|
+
to_return(:status => 200, :body => fixture('chunked_upload'))
|
22
|
+
|
23
|
+
stub_request(:post, "https://api-content.dropbox.com/1/commit_chunked_upload/dropbox/foo.txt?upload_id=v0k84B0AT9fYkfMUp0sBTA").
|
24
|
+
with(:headers => {'Accept'=>'*/*', 'Authorization'=>/OAuth oauth_body_hash="\S+", oauth_consumer_key="#{app_key}", oauth_nonce="\S+", oauth_signature="\S+", oauth_signature_method="HMAC-SHA1", oauth_timestamp="\S+", oauth_token="#{app_token}", oauth_version="1.0"/, 'Content-Length'=>'0', 'Content-Type'=>'application/octet-stream', 'User-Agent'=>'OAuth gem v0.4.7'}).
|
25
|
+
to_return(:status => 200, :body => fixture('commit_chunked_upload'), :headers => {})
|
26
|
+
|
27
|
+
@cli.chunked_upload('foo.txt')
|
28
|
+
expect($stdout.string).to eq <<-eos
|
29
|
+
Starting chunked upload
|
30
|
+
Total Size: 21 bytes
|
31
|
+
Time: 00:00:00 <==========================================> 100% Upload progress
|
32
|
+
File uploaded successfully!
|
33
|
+
eos
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|