filestack 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/README.md +2 -2
- data/VERSION +1 -1
- data/docs/AV.html +557 -0
- data/docs/Filestack.html +115 -0
- data/docs/Filestack/Ruby.html +115 -0
- data/docs/FilestackClient.html +702 -0
- data/docs/FilestackCommon.html +884 -0
- data/docs/FilestackConfig.html +197 -0
- data/docs/FilestackFilelink.html +1277 -0
- data/docs/FilestackSecurity.html +654 -0
- data/docs/IntelligentState.html +729 -0
- data/docs/IntelligentUtils.html +1639 -0
- data/docs/MultipartUploadUtils.html +1543 -0
- data/docs/Transform.html +1152 -0
- data/docs/TransformConfig.html +138 -0
- data/docs/TransformUtils.html +272 -0
- data/docs/UploadUtils.html +673 -0
- data/docs/_index.html +227 -0
- data/docs/class_list.html +51 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +58 -0
- data/docs/css/style.css +492 -0
- data/docs/file.README.html +210 -0
- data/docs/file_list.html +56 -0
- data/docs/frames.html +17 -0
- data/docs/index.html +210 -0
- data/docs/js/app.js +248 -0
- data/docs/js/full_list.js +216 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +643 -0
- data/docs/top-level-namespace.html +145 -0
- data/examples/file_transformations.rb +6 -0
- data/examples/intelligent_upload.rb +7 -0
- data/examples/normal_upload.rb +5 -0
- data/examples/upload_external_url.rb +7 -0
- data/examples/upload_with_security.rb +6 -0
- data/examples/video_convert.rb +10 -0
- data/filestack-ruby.gemspec +1 -0
- data/lib/filestack/config.rb +9 -5
- data/lib/filestack/mixins/filestack_common.rb +17 -1
- data/lib/filestack/models/filelink.rb +8 -1
- data/lib/filestack/models/filestack_client.rb +17 -3
- data/lib/filestack/ruby/version.rb +1 -1
- data/lib/filestack/utils/multipart_upload_utils.rb +91 -36
- data/lib/filestack/utils/utils.rb +309 -1
- metadata +52 -3
@@ -0,0 +1,145 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
+
<title>
|
7
|
+
Top Level Namespace
|
8
|
+
|
9
|
+
— Documentation by YARD 0.9.9
|
10
|
+
|
11
|
+
</title>
|
12
|
+
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" charset="utf-8" />
|
14
|
+
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" charset="utf-8" />
|
16
|
+
|
17
|
+
<script type="text/javascript" charset="utf-8">
|
18
|
+
pathId = "";
|
19
|
+
relpath = '';
|
20
|
+
</script>
|
21
|
+
|
22
|
+
|
23
|
+
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
24
|
+
|
25
|
+
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
26
|
+
|
27
|
+
|
28
|
+
</head>
|
29
|
+
<body>
|
30
|
+
<div class="nav_wrap">
|
31
|
+
<iframe id="nav" src="class_list.html?1"></iframe>
|
32
|
+
<div id="resizer"></div>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<div id="main" tabindex="-1">
|
36
|
+
<div id="header">
|
37
|
+
<div id="menu">
|
38
|
+
|
39
|
+
<a href="_index.html">Index</a> »
|
40
|
+
|
41
|
+
|
42
|
+
<span class="title">Top Level Namespace</span>
|
43
|
+
|
44
|
+
</div>
|
45
|
+
|
46
|
+
<div id="search">
|
47
|
+
|
48
|
+
<a class="full_list_link" id="class_list_link"
|
49
|
+
href="class_list.html">
|
50
|
+
|
51
|
+
<svg width="24" height="24">
|
52
|
+
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
53
|
+
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
54
|
+
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
55
|
+
</svg>
|
56
|
+
</a>
|
57
|
+
|
58
|
+
</div>
|
59
|
+
<div class="clear"></div>
|
60
|
+
</div>
|
61
|
+
|
62
|
+
<div id="content"><h1>Top Level Namespace
|
63
|
+
|
64
|
+
|
65
|
+
|
66
|
+
</h1>
|
67
|
+
<div class="box_info">
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
<dl>
|
75
|
+
<dt>Includes:</dt>
|
76
|
+
<dd><span class='object_link'><a href="Filestack.html" title="Filestack (module)">Filestack</a></span>, <span class='object_link'><a href="IntelligentUtils.html" title="IntelligentUtils (module)">IntelligentUtils</a></span>, <span class='object_link'><a href="UploadUtils.html" title="UploadUtils (module)">UploadUtils</a></span></dd>
|
77
|
+
</dl>
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
</div>
|
85
|
+
|
86
|
+
<h2>Defined Under Namespace</h2>
|
87
|
+
<p class="children">
|
88
|
+
|
89
|
+
|
90
|
+
<strong class="modules">Modules:</strong> <span class='object_link'><a href="Filestack.html" title="Filestack (module)">Filestack</a></span>, <span class='object_link'><a href="FilestackCommon.html" title="FilestackCommon (module)">FilestackCommon</a></span>, <span class='object_link'><a href="IntelligentUtils.html" title="IntelligentUtils (module)">IntelligentUtils</a></span>, <span class='object_link'><a href="MultipartUploadUtils.html" title="MultipartUploadUtils (module)">MultipartUploadUtils</a></span>, <span class='object_link'><a href="TransformUtils.html" title="TransformUtils (module)">TransformUtils</a></span>, <span class='object_link'><a href="UploadUtils.html" title="UploadUtils (module)">UploadUtils</a></span>
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
<strong class="classes">Classes:</strong> <span class='object_link'><a href="AV.html" title="AV (class)">AV</a></span>, <span class='object_link'><a href="FilestackClient.html" title="FilestackClient (class)">FilestackClient</a></span>, <span class='object_link'><a href="FilestackConfig.html" title="FilestackConfig (class)">FilestackConfig</a></span>, <span class='object_link'><a href="FilestackFilelink.html" title="FilestackFilelink (class)">FilestackFilelink</a></span>, <span class='object_link'><a href="FilestackSecurity.html" title="FilestackSecurity (class)">FilestackSecurity</a></span>, <span class='object_link'><a href="IntelligentState.html" title="IntelligentState (class)">IntelligentState</a></span>, <span class='object_link'><a href="Transform.html" title="Transform (class)">Transform</a></span>, <span class='object_link'><a href="TransformConfig.html" title="TransformConfig (class)">TransformConfig</a></span>
|
95
|
+
|
96
|
+
|
97
|
+
</p>
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
|
110
|
+
|
111
|
+
|
112
|
+
<h2>Method Summary</h2>
|
113
|
+
|
114
|
+
<h3 class="inherited">Methods included from <span class='object_link'><a href="IntelligentUtils.html" title="IntelligentUtils (module)">IntelligentUtils</a></span></h3>
|
115
|
+
<p class="inherited"><span class='object_link'><a href="IntelligentUtils.html#bad_state-instance_method" title="IntelligentUtils#bad_state (method)">#bad_state</a></span>, <span class='object_link'><a href="IntelligentUtils.html#change_offset-instance_method" title="IntelligentUtils#change_offset (method)">#change_offset</a></span>, <span class='object_link'><a href="IntelligentUtils.html#chunk_job-instance_method" title="IntelligentUtils#chunk_job (method)">#chunk_job</a></span>, <span class='object_link'><a href="IntelligentUtils.html#create_intelligent_generator-instance_method" title="IntelligentUtils#create_intelligent_generator (method)">#create_intelligent_generator</a></span>, <span class='object_link'><a href="IntelligentUtils.html#create_upload_job_chunks-instance_method" title="IntelligentUtils#create_upload_job_chunks (method)">#create_upload_job_chunks</a></span>, <span class='object_link'><a href="IntelligentUtils.html#get_generator_batch-instance_method" title="IntelligentUtils#get_generator_batch (method)">#get_generator_batch</a></span>, <span class='object_link'><a href="IntelligentUtils.html#run_intelligent_upload_flow-instance_method" title="IntelligentUtils#run_intelligent_upload_flow (method)">#run_intelligent_upload_flow</a></span>, <span class='object_link'><a href="IntelligentUtils.html#run_intelligent_uploads-instance_method" title="IntelligentUtils#run_intelligent_uploads (method)">#run_intelligent_uploads</a></span>, <span class='object_link'><a href="IntelligentUtils.html#upload_chunk_intelligently-instance_method" title="IntelligentUtils#upload_chunk_intelligently (method)">#upload_chunk_intelligently</a></span></p>
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
|
120
|
+
|
121
|
+
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
<h3 class="inherited">Methods included from <span class='object_link'><a href="UploadUtils.html" title="UploadUtils (module)">UploadUtils</a></span></h3>
|
126
|
+
<p class="inherited"><span class='object_link'><a href="UploadUtils.html#get_url-instance_method" title="UploadUtils#get_url (method)">#get_url</a></span>, <span class='object_link'><a href="UploadUtils.html#make_call-instance_method" title="UploadUtils#make_call (method)">#make_call</a></span>, <span class='object_link'><a href="UploadUtils.html#send_upload-instance_method" title="UploadUtils#send_upload (method)">#send_upload</a></span></p>
|
127
|
+
|
128
|
+
|
129
|
+
|
130
|
+
|
131
|
+
|
132
|
+
|
133
|
+
|
134
|
+
|
135
|
+
</div>
|
136
|
+
|
137
|
+
<div id="footer">
|
138
|
+
Generated on Thu Aug 17 10:04:38 2017 by
|
139
|
+
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
140
|
+
0.9.9 (ruby-2.4.0).
|
141
|
+
</div>
|
142
|
+
|
143
|
+
</div>
|
144
|
+
</body>
|
145
|
+
</html>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
require 'filestack'
|
2
|
+
|
3
|
+
# intelligent upload flow requires you to pass in the intelligent parameter
|
4
|
+
# and have the service enabled on your application
|
5
|
+
client = FilestackClient.new('APIKEY')
|
6
|
+
filelink = client.upload(filepath: 'test-files/doom.mp4', intelligent: true)
|
7
|
+
puts filelink.url
|
@@ -0,0 +1,7 @@
|
|
1
|
+
require 'filestack'
|
2
|
+
|
3
|
+
# intelligent upload flow requires you to pass in the intelligent parameter
|
4
|
+
# and have the service enabled on your application
|
5
|
+
client = FilestackClient.new('APIKEY')
|
6
|
+
filelink = client.upload(external_url: 'http://trailers.divx.com/divx_prod/profiles/WiegelesHeliSki_DivXPlus_19Mbps.mkv')
|
7
|
+
puts filelink.url
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'filestack'
|
2
|
+
|
3
|
+
client = FilestackClient.new('APIKEY')
|
4
|
+
filelink = client.upload(filepath: 'test-files/doom.mp4')
|
5
|
+
video = filelink.transform.av_convert(width: 100, height: 100)
|
6
|
+
while video.status != 'completed'
|
7
|
+
puts video.status
|
8
|
+
end
|
9
|
+
filelink = video.to_filelink
|
10
|
+
puts filelink.url
|
data/filestack-ruby.gemspec
CHANGED
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_dependency "unirest", "~> 1.1.2"
|
26
26
|
spec.add_dependency "parallel", "~> 1.11.2"
|
27
27
|
spec.add_dependency "mimemagic", "~> 0.3.2"
|
28
|
+
spec.add_dependency "progress_bar"
|
28
29
|
|
29
30
|
spec.add_development_dependency "bundler", "~> 1.7"
|
30
31
|
spec.add_development_dependency "rake", "~> 10.0"
|
data/lib/filestack/config.rb
CHANGED
@@ -7,21 +7,25 @@ class FilestackConfig
|
|
7
7
|
CDN_URL = 'https://cdn.filestackcontent.com'.freeze
|
8
8
|
PROCESS_URL = 'https://process.filestackapi.com'.freeze
|
9
9
|
|
10
|
-
MULTIPART_START_URL = 'https://upload.filestackapi.com/multipart/start'.freeze
|
11
|
-
MULTIPART_UPLOAD_URL = 'https://upload.filestackapi.com/multipart/upload'.freeze
|
12
|
-
|
10
|
+
MULTIPART_START_URL = 'https://rc-upload.filestackapi.com/multipart/start'.freeze
|
11
|
+
MULTIPART_UPLOAD_URL = 'https://rc-upload.filestackapi.com/multipart/upload'.freeze
|
12
|
+
MULTIPART_COMMIT_URL = 'https://rc-upload.filestackapi.com/multipart/commit'.freeze
|
13
|
+
MULTIPART_COMPLETE_URL = 'https://rc-upload.filestackapi.com/multipart/complete'.freeze
|
13
14
|
|
14
15
|
MULTIPART_PARAMS = %w[
|
15
16
|
store_location store_region store_container
|
16
17
|
store_path store_access
|
17
18
|
].freeze
|
18
19
|
|
19
|
-
DEFAULT_CHUNK_SIZE =
|
20
|
+
DEFAULT_CHUNK_SIZE = 8 * 1024**2
|
21
|
+
DEFAULT_OFFSET_SIZE = 1 * 1024**2
|
20
22
|
VERSION = Filestack::Ruby::VERSION
|
21
23
|
HEADERS = {
|
22
24
|
'User-Agent' => "filestack-ruby #{VERSION}",
|
23
25
|
'Filestack-Source' => "Ruby-#{VERSION}"
|
24
26
|
}.freeze
|
27
|
+
|
28
|
+
INTELLIGENT_ERROR_MESSAGES = ['BACKEND_SERVER', 'BACKEND_NETWORK', 'S3_SERVER', 'S3_NETWORK']
|
25
29
|
end
|
26
30
|
|
27
31
|
class TransformConfig
|
@@ -31,6 +35,6 @@ class TransformConfig
|
|
31
35
|
torn_edges shadow circle border sharpen blur monochrome
|
32
36
|
blackwhite sepia pixelate oil_paint negative modulate
|
33
37
|
partial_pixelate partial_blur collage upscale enhance
|
34
|
-
redeye ascii filetype_conversion quality
|
38
|
+
redeye ascii filetype_conversion quality urlscreenshot
|
35
39
|
].freeze
|
36
40
|
end
|
@@ -23,7 +23,7 @@ module FilestackCommon
|
|
23
23
|
# @param [String] filepath Local path of file to be written
|
24
24
|
#
|
25
25
|
# @return [Int] Size of file written
|
26
|
-
def send_download(filepath)
|
26
|
+
def send_download(url, filepath)
|
27
27
|
content = send_get_content(url)
|
28
28
|
File.write(filepath, content.body)
|
29
29
|
end
|
@@ -90,4 +90,20 @@ module FilestackCommon
|
|
90
90
|
"security=signature:#{signature},policy:#{policy}/#{handle}"
|
91
91
|
UploadUtils.make_call(url, 'get').body[task]
|
92
92
|
end
|
93
|
+
|
94
|
+
def send_metadata(handle, security = nil, params)
|
95
|
+
if security
|
96
|
+
policy = security.policy
|
97
|
+
signature = security.signature
|
98
|
+
url = "#{FilestackConfig::CDN_URL}/#{handle}/metadata?signature=#{signature}&policy=#{policy}"
|
99
|
+
else
|
100
|
+
url = "#{FilestackConfig::CDN_URL}/#{handle}/metadata"
|
101
|
+
end
|
102
|
+
response = UploadUtils.make_call(url, 'get', parameters: params)
|
103
|
+
|
104
|
+
if response.code == 200
|
105
|
+
return response.body
|
106
|
+
end
|
107
|
+
raise response.body
|
108
|
+
end
|
93
109
|
end
|
@@ -37,7 +37,7 @@ class FilestackFilelink
|
|
37
37
|
# downloaded filelink
|
38
38
|
# @return [Unirest::Response]
|
39
39
|
def download(filepath)
|
40
|
-
send_download(filepath)
|
40
|
+
send_download(url, filepath)
|
41
41
|
end
|
42
42
|
|
43
43
|
# Delete filelink
|
@@ -71,6 +71,13 @@ class FilestackFilelink
|
|
71
71
|
send_tags('tags', @handle, @security)
|
72
72
|
end
|
73
73
|
|
74
|
+
# Return metadata for file handle
|
75
|
+
#
|
76
|
+
# @return [Unirest::Response]
|
77
|
+
def metadata(params = {})
|
78
|
+
send_metadata(@handle, @security, params)
|
79
|
+
end
|
80
|
+
|
74
81
|
# Return true (SFW) or false (NSFW)
|
75
82
|
#
|
76
83
|
# @return [Bool]
|
@@ -1,6 +1,8 @@
|
|
1
|
+
require 'filestack/config'
|
1
2
|
require 'filestack/utils/multipart_upload_utils'
|
2
3
|
require 'filestack/models/filestack_transform'
|
3
4
|
require 'filestack/utils/utils'
|
5
|
+
require 'json'
|
4
6
|
|
5
7
|
# The Filestack FilestackClient class acts as a hub for all
|
6
8
|
# Filestack actions that do not require a file handle, including
|
@@ -29,12 +31,12 @@ class FilestackClient
|
|
29
31
|
# @param [Hash] options User-supplied upload options
|
30
32
|
#
|
31
33
|
# return [Filestack::FilestackFilelink]
|
32
|
-
def upload(filepath: nil, external_url: nil, multipart: true, options: nil, storage: 's3')
|
34
|
+
def upload(filepath: nil, external_url: nil, multipart: true, options: nil, storage: 's3', intelligent: false, timeout: 60)
|
33
35
|
if filepath && external_url
|
34
36
|
return 'You cannot upload a URL and file at the same time'
|
35
37
|
end
|
36
38
|
response = if filepath && multipart
|
37
|
-
multipart_upload(@apikey, filepath, @security, options)
|
39
|
+
multipart_upload(@apikey, filepath, @security, options, timeout, intelligent: intelligent)
|
38
40
|
else
|
39
41
|
send_upload(
|
40
42
|
@apikey,
|
@@ -47,8 +49,20 @@ class FilestackClient
|
|
47
49
|
end
|
48
50
|
FilestackFilelink.new(response['handle'], security: @security, apikey: @apikey)
|
49
51
|
end
|
50
|
-
|
52
|
+
# Transform an external URL
|
53
|
+
#
|
54
|
+
# @param [string] external_url A valid URL
|
55
|
+
#
|
56
|
+
# @return [Filestack::Transform]
|
51
57
|
def transform_external(external_url)
|
52
58
|
Transform.new(external_url: external_url, security: @security, apikey: @apikey)
|
59
|
+
end
|
60
|
+
|
61
|
+
def zip(destination, files)
|
62
|
+
encoded_files = JSON.generate(files).gsub('"', '')
|
63
|
+
zip_url = "#{FilestackConfig::CDN_URL}/#{@apikey}/zip/#{encoded_files}"
|
64
|
+
escaped_zip_url = zip_url.gsub("[","%5B").gsub("]","%5D")
|
65
|
+
response = UploadUtils.make_call(escaped_zip_url, 'get')
|
66
|
+
File.write(destination, response.body)
|
53
67
|
end
|
54
68
|
end
|
@@ -4,18 +4,22 @@ require 'mimemagic'
|
|
4
4
|
require 'json'
|
5
5
|
require 'parallel'
|
6
6
|
require 'unirest'
|
7
|
-
|
7
|
+
require 'progress_bar'
|
8
8
|
require 'filestack/config'
|
9
9
|
require 'filestack/utils/utils'
|
10
10
|
|
11
11
|
include UploadUtils
|
12
|
-
|
12
|
+
include IntelligentUtils
|
13
|
+
Unirest.timeout(30)
|
13
14
|
# Includes all the utility functions for Filestack multipart uploads
|
14
15
|
module MultipartUploadUtils
|
15
16
|
def get_file_info(file)
|
16
17
|
filename = File.basename(file)
|
17
18
|
filesize = File.size(file)
|
18
19
|
mimetype = MimeMagic.by_magic(File.open(file))
|
20
|
+
if mimetype.nil?
|
21
|
+
mimetype = 'application/octet-stream'
|
22
|
+
end
|
19
23
|
[filename, filesize, mimetype.to_s]
|
20
24
|
end
|
21
25
|
|
@@ -38,9 +42,10 @@ module MultipartUploadUtils
|
|
38
42
|
mimetype: mimetype,
|
39
43
|
size: filesize,
|
40
44
|
store_location: options.nil? ? 's3' : options[:store_location],
|
41
|
-
file: Tempfile.new(filename)
|
45
|
+
file: Tempfile.new(filename),
|
46
|
+
options: options,
|
47
|
+
'multipart' => 'true'
|
42
48
|
}
|
43
|
-
|
44
49
|
params = params.merge!(options) if options
|
45
50
|
|
46
51
|
unless security.nil?
|
@@ -55,7 +60,7 @@ module MultipartUploadUtils
|
|
55
60
|
if response.code == 200
|
56
61
|
response.body
|
57
62
|
else
|
58
|
-
raise
|
63
|
+
raise RuntimeError.new(response.body)
|
59
64
|
end
|
60
65
|
end
|
61
66
|
|
@@ -67,8 +72,6 @@ module MultipartUploadUtils
|
|
67
72
|
# @param [Int] filesize Size of incoming file
|
68
73
|
# @param [Unirest::Response] start_response Response body from
|
69
74
|
# multipart_start
|
70
|
-
# @param [FilestackSecurity] security Security object with
|
71
|
-
# policy/signature
|
72
75
|
# @param [Hash] options User-defined options for
|
73
76
|
# multipart uploads
|
74
77
|
#
|
@@ -78,24 +81,35 @@ module MultipartUploadUtils
|
|
78
81
|
part = 1
|
79
82
|
seek_point = 0
|
80
83
|
while seek_point < filesize
|
81
|
-
|
84
|
+
part_info = {
|
82
85
|
seek: seek_point,
|
83
86
|
filepath: filepath,
|
84
87
|
filename: filename,
|
85
88
|
apikey: apikey,
|
86
89
|
part: part,
|
90
|
+
filesize: filesize,
|
87
91
|
uri: start_response['uri'],
|
88
92
|
region: start_response['region'],
|
89
93
|
upload_id: start_response['upload_id'],
|
90
94
|
location_url: start_response['location_url'],
|
95
|
+
start_response: start_response,
|
96
|
+
options: options,
|
91
97
|
store_location: options.nil? ? 's3' : options[:store_location]
|
92
|
-
|
98
|
+
}
|
99
|
+
if seek_point + FilestackConfig::DEFAULT_CHUNK_SIZE > filesize
|
100
|
+
size = filesize - (seek_point)
|
101
|
+
else
|
102
|
+
size = FilestackConfig::DEFAULT_CHUNK_SIZE
|
103
|
+
end
|
104
|
+
part_info[:size] = size
|
105
|
+
jobs.push(part_info)
|
93
106
|
part += 1
|
94
107
|
seek_point += FilestackConfig::DEFAULT_CHUNK_SIZE
|
95
108
|
end
|
96
109
|
jobs
|
97
110
|
end
|
98
111
|
|
112
|
+
|
99
113
|
# Uploads one chunk of the file
|
100
114
|
#
|
101
115
|
# @param [Hash] job Hash of options needed
|
@@ -112,6 +126,7 @@ module MultipartUploadUtils
|
|
112
126
|
file = File.open(filepath)
|
113
127
|
file.seek(job[:seek])
|
114
128
|
chunk = file.read(FilestackConfig::DEFAULT_CHUNK_SIZE)
|
129
|
+
|
115
130
|
md5 = Digest::MD5.new
|
116
131
|
md5 << chunk
|
117
132
|
data = {
|
@@ -122,7 +137,7 @@ module MultipartUploadUtils
|
|
122
137
|
uri: job[:uri],
|
123
138
|
region: job[:region],
|
124
139
|
upload_id: job[:upload_id],
|
125
|
-
store_location:
|
140
|
+
store_location: job[:store_location],
|
126
141
|
file: Tempfile.new(job[:filename])
|
127
142
|
}
|
128
143
|
data = data.merge!(options) if options
|
@@ -134,7 +149,6 @@ module MultipartUploadUtils
|
|
134
149
|
fs_response['url'], headers: fs_response['headers'], parameters: chunk
|
135
150
|
)
|
136
151
|
end
|
137
|
-
|
138
152
|
# Runs all jobs in parallel
|
139
153
|
#
|
140
154
|
# @param [Array] jobs Array of jobs to be run
|
@@ -145,17 +159,20 @@ module MultipartUploadUtils
|
|
145
159
|
#
|
146
160
|
# @return [Array] Array of parts/etags strings
|
147
161
|
def run_uploads(jobs, apikey, filepath, options)
|
148
|
-
|
162
|
+
bar = ProgressBar.new(jobs.length)
|
163
|
+
results = Parallel.map(jobs, in_threads: 4) do |job|
|
149
164
|
response = upload_chunk(
|
150
165
|
job, apikey, filepath, options
|
151
166
|
)
|
152
|
-
|
153
|
-
|
154
|
-
|
167
|
+
if response.code == 200
|
168
|
+
bar.increment!
|
169
|
+
part = job[:part]
|
170
|
+
etag = response.headers[:etag]
|
171
|
+
"#{part}:#{etag}"
|
172
|
+
end
|
155
173
|
end
|
156
174
|
results
|
157
175
|
end
|
158
|
-
|
159
176
|
# Send complete call to multipart endpoint
|
160
177
|
#
|
161
178
|
# @param [String] apikey Filestack API key
|
@@ -173,20 +190,34 @@ module MultipartUploadUtils
|
|
173
190
|
# multipart uploads
|
174
191
|
#
|
175
192
|
# @return [Unirest::Response]
|
176
|
-
def multipart_complete(apikey, filename, filesize, mimetype, start_response, parts_and_etags, options)
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
193
|
+
def multipart_complete(apikey, filename, filesize, mimetype, start_response, parts_and_etags, options, intelligent = false)
|
194
|
+
if !intelligent
|
195
|
+
data = {
|
196
|
+
apikey: apikey,
|
197
|
+
uri: start_response['uri'],
|
198
|
+
region: start_response['region'],
|
199
|
+
upload_id: start_response['upload_id'],
|
200
|
+
filename: filename,
|
201
|
+
size: filesize,
|
202
|
+
mimetype: mimetype,
|
203
|
+
parts: parts_and_etags.join(';'),
|
204
|
+
store_location: options.nil? ? 's3' : options[:store_location],
|
205
|
+
file: Tempfile.new(filename)
|
206
|
+
}
|
207
|
+
else
|
208
|
+
data = {
|
209
|
+
apikey: apikey,
|
210
|
+
uri: start_response['uri'],
|
211
|
+
region: start_response['region'],
|
212
|
+
upload_id: start_response['upload_id'],
|
213
|
+
filename: filename,
|
214
|
+
size: filesize,
|
215
|
+
mimetype: mimetype,
|
216
|
+
store_location: options.nil? ? 's3' : options[:store_location],
|
217
|
+
file: Tempfile.new(filename),
|
218
|
+
'multipart' => 'true'
|
219
|
+
}
|
220
|
+
end
|
190
221
|
data = data.merge!(options) if options
|
191
222
|
|
192
223
|
Unirest.post(
|
@@ -205,19 +236,43 @@ module MultipartUploadUtils
|
|
205
236
|
# multipart uploads
|
206
237
|
#
|
207
238
|
# @return [Unirest::Response]
|
208
|
-
def multipart_upload(apikey, filepath, security, options)
|
239
|
+
def multipart_upload(apikey, filepath, security, options, timeout, intelligent: false)
|
209
240
|
filename, filesize, mimetype = get_file_info(filepath)
|
210
241
|
start_response = multipart_start(
|
211
242
|
apikey, filename, filesize, mimetype, security, options
|
212
243
|
)
|
244
|
+
unless start_response['upload_type'].nil?
|
245
|
+
intelligent_enabled = ((start_response['upload_type'].include? 'intelligent_ingestion')) && intelligent
|
246
|
+
end
|
213
247
|
jobs = create_upload_jobs(
|
214
248
|
apikey, filename, filepath, filesize, start_response, options
|
215
249
|
)
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
250
|
+
if intelligent_enabled
|
251
|
+
state = IntelligentState.new
|
252
|
+
run_intelligent_upload_flow(jobs, state)
|
253
|
+
response_complete = multipart_complete(
|
254
|
+
apikey, filename, filesize, mimetype,
|
255
|
+
start_response, nil, options, intelligent
|
256
|
+
)
|
257
|
+
else
|
258
|
+
parts_and_etags = run_uploads(jobs, apikey, filepath, options)
|
259
|
+
response_complete = multipart_complete(
|
260
|
+
apikey, filename, filesize, mimetype,
|
261
|
+
start_response, parts_and_etags, options
|
262
|
+
)
|
263
|
+
end
|
264
|
+
begin
|
265
|
+
Timeout::timeout(timeout){
|
266
|
+
while response_complete.code == 202
|
267
|
+
response_complete = multipart_complete(
|
268
|
+
apikey, filename, filesize, mimetype,
|
269
|
+
start_response, nil, options, intelligent
|
270
|
+
)
|
271
|
+
end
|
272
|
+
}
|
273
|
+
rescue
|
274
|
+
raise "Upload timed out upon completion. Please try again later"
|
275
|
+
end
|
221
276
|
response_complete.body
|
222
277
|
end
|
223
278
|
end
|