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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +3 -0
  3. data/README.md +2 -2
  4. data/VERSION +1 -1
  5. data/docs/AV.html +557 -0
  6. data/docs/Filestack.html +115 -0
  7. data/docs/Filestack/Ruby.html +115 -0
  8. data/docs/FilestackClient.html +702 -0
  9. data/docs/FilestackCommon.html +884 -0
  10. data/docs/FilestackConfig.html +197 -0
  11. data/docs/FilestackFilelink.html +1277 -0
  12. data/docs/FilestackSecurity.html +654 -0
  13. data/docs/IntelligentState.html +729 -0
  14. data/docs/IntelligentUtils.html +1639 -0
  15. data/docs/MultipartUploadUtils.html +1543 -0
  16. data/docs/Transform.html +1152 -0
  17. data/docs/TransformConfig.html +138 -0
  18. data/docs/TransformUtils.html +272 -0
  19. data/docs/UploadUtils.html +673 -0
  20. data/docs/_index.html +227 -0
  21. data/docs/class_list.html +51 -0
  22. data/docs/css/common.css +1 -0
  23. data/docs/css/full_list.css +58 -0
  24. data/docs/css/style.css +492 -0
  25. data/docs/file.README.html +210 -0
  26. data/docs/file_list.html +56 -0
  27. data/docs/frames.html +17 -0
  28. data/docs/index.html +210 -0
  29. data/docs/js/app.js +248 -0
  30. data/docs/js/full_list.js +216 -0
  31. data/docs/js/jquery.js +4 -0
  32. data/docs/method_list.html +643 -0
  33. data/docs/top-level-namespace.html +145 -0
  34. data/examples/file_transformations.rb +6 -0
  35. data/examples/intelligent_upload.rb +7 -0
  36. data/examples/normal_upload.rb +5 -0
  37. data/examples/upload_external_url.rb +7 -0
  38. data/examples/upload_with_security.rb +6 -0
  39. data/examples/video_convert.rb +10 -0
  40. data/filestack-ruby.gemspec +1 -0
  41. data/lib/filestack/config.rb +9 -5
  42. data/lib/filestack/mixins/filestack_common.rb +17 -1
  43. data/lib/filestack/models/filelink.rb +8 -1
  44. data/lib/filestack/models/filestack_client.rb +17 -3
  45. data/lib/filestack/ruby/version.rb +1 -1
  46. data/lib/filestack/utils/multipart_upload_utils.rb +91 -36
  47. data/lib/filestack/utils/utils.rb +309 -1
  48. 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
+ &mdash; 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> &raquo;
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,6 @@
1
+ require 'filestack'
2
+
3
+ client = FilestackClient.new('APIKEY')
4
+ filelink = client.upload(filepath: 'test-files/calvinandhobbes.jpg')
5
+ transform = filelink.transform.resize(width: 100, height:100)
6
+ puts transform.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(filepath: 'test-files/doom.mp4', intelligent: true)
7
+ puts filelink.url
@@ -0,0 +1,5 @@
1
+ require 'filestack'
2
+
3
+ client = FilestackClient.new('APIKEY')
4
+ filelink = client.upload(filepath: 'test-files/doom.mp4')
5
+ 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,6 @@
1
+ require 'filestack'
2
+
3
+ security = FilestackSecurity.new('APP_SECRET')
4
+ client = FilestackClient.new('APIKEY', security: security)
5
+ filelink = client.upload(filepath: 'test-files/doom.mp4')
6
+ 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
@@ -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"
@@ -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
- MULTIPART_COMPLETE_URL = 'https://upload.filestackapi.com/multipart/complete'.freeze
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 = 5 * 1024**2
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
@@ -1,5 +1,5 @@
1
1
  module Filestack
2
2
  module Ruby
3
- VERSION = '2.1.0'.freeze
3
+ VERSION = '2.2.0'.freeze
4
4
  end
5
5
  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 Exception(response.body)
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
- jobs.push(
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: options.nil? ? 's3' : options[: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
- results = Parallel.map(jobs) do |job|
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
- part = job[:part]
153
- etag = response.headers[:etag]
154
- "#{part}:#{etag}"
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
- data = {
178
- apikey: apikey,
179
- uri: start_response['uri'],
180
- region: start_response['region'],
181
- upload_id: start_response['upload_id'],
182
- filename: filename,
183
- size: filesize,
184
- mimetype: mimetype,
185
- parts: parts_and_etags.join(';'),
186
- store_location: options.nil? ? 's3' : options[:store_location],
187
- file: Tempfile.new(filename)
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
- parts_and_etags = run_uploads(jobs, apikey, filepath, options)
217
- response_complete = multipart_complete(
218
- apikey, filename, filesize, mimetype,
219
- start_response, parts_and_etags, options
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