uploadcare-ruby 4.4.2 → 5.0.0.rc1

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 (178) hide show
  1. checksums.yaml +4 -4
  2. data/.env.example +7 -0
  3. data/.github/workflows/gem-push.yml +1 -1
  4. data/.github/workflows/ruby.yml +10 -13
  5. data/.gitignore +9 -0
  6. data/.rubocop.yml +95 -8
  7. data/CHANGELOG.md +78 -0
  8. data/Gemfile +23 -6
  9. data/MIGRATING_V5.md +290 -0
  10. data/README.md +422 -671
  11. data/Rakefile +5 -1
  12. data/api_examples/README.md +77 -0
  13. data/api_examples/rest_api/delete_files_storage.rb +3 -5
  14. data/api_examples/rest_api/delete_files_uuid_metadata_key.rb +3 -4
  15. data/api_examples/rest_api/delete_files_uuid_storage.rb +3 -4
  16. data/api_examples/rest_api/delete_groups_uuid.rb +3 -4
  17. data/api_examples/rest_api/delete_webhooks_unsubscribe.rb +3 -4
  18. data/api_examples/rest_api/get_addons_aws_rekognition_detect_labels_execute_status.rb +3 -6
  19. data/api_examples/rest_api/get_addons_aws_rekognition_detect_moderation_labels_execute_status.rb +3 -6
  20. data/api_examples/rest_api/get_addons_remove_bg_execute_status.rb +3 -6
  21. data/api_examples/rest_api/get_addons_uc_clamav_virus_scan_execute_status.rb +3 -6
  22. data/api_examples/rest_api/get_convert_document_status_token.rb +3 -5
  23. data/api_examples/rest_api/get_convert_document_uuid.rb +3 -5
  24. data/api_examples/rest_api/get_convert_video_status_token.rb +3 -5
  25. data/api_examples/rest_api/get_files.rb +3 -5
  26. data/api_examples/rest_api/get_files_uuid.rb +3 -5
  27. data/api_examples/rest_api/get_files_uuid_metadata.rb +3 -5
  28. data/api_examples/rest_api/get_files_uuid_metadata_key.rb +3 -5
  29. data/api_examples/rest_api/get_groups.rb +3 -5
  30. data/api_examples/rest_api/get_groups_uuid.rb +3 -5
  31. data/api_examples/rest_api/get_project.rb +3 -5
  32. data/api_examples/rest_api/get_webhooks.rb +3 -5
  33. data/api_examples/rest_api/post_addons_aws_rekognition_detect_labels_execute.rb +3 -5
  34. data/api_examples/rest_api/post_addons_aws_rekognition_detect_moderation_labels_execute.rb +3 -5
  35. data/api_examples/rest_api/post_addons_remove_bg_execute.rb +3 -5
  36. data/api_examples/rest_api/post_addons_uc_clamav_virus_scan_execute.rb +3 -5
  37. data/api_examples/rest_api/post_convert_document.rb +3 -6
  38. data/api_examples/rest_api/post_convert_video.rb +3 -10
  39. data/api_examples/rest_api/post_files_local_copy.rb +3 -6
  40. data/api_examples/rest_api/post_files_remote_copy.rb +3 -7
  41. data/api_examples/rest_api/post_webhooks.rb +3 -9
  42. data/api_examples/rest_api/put_files_storage.rb +3 -8
  43. data/api_examples/rest_api/put_files_uuid_metadata_key.rb +3 -7
  44. data/api_examples/rest_api/put_files_uuid_storage.rb +3 -5
  45. data/api_examples/rest_api/put_webhooks_id.rb +3 -11
  46. data/api_examples/support/example_helper.rb +250 -0
  47. data/api_examples/support/run_rest_example.rb +161 -0
  48. data/api_examples/support/run_upload_example.rb +88 -0
  49. data/api_examples/upload_api/get_from_url_status.rb +3 -5
  50. data/api_examples/upload_api/get_group_info.rb +3 -6
  51. data/api_examples/upload_api/get_info.rb +3 -6
  52. data/api_examples/upload_api/post_base.rb +3 -5
  53. data/api_examples/upload_api/post_from_url.rb +3 -5
  54. data/api_examples/upload_api/post_group.rb +3 -8
  55. data/api_examples/upload_api/post_multipart_complete.rb +3 -7
  56. data/api_examples/upload_api/post_multipart_start.rb +3 -7
  57. data/api_examples/upload_api/put_multipart_part.rb +4 -0
  58. data/bin/console +1 -1
  59. data/docs/release-notes-5.0.0.rc1.md +34 -0
  60. data/examples/README.md +39 -0
  61. data/examples/batch_upload.rb +54 -0
  62. data/examples/group_creation.rb +88 -0
  63. data/examples/large_file_upload.rb +88 -0
  64. data/examples/simple_upload.rb +39 -0
  65. data/examples/upload_with_progress.rb +84 -0
  66. data/examples/url_upload.rb +56 -0
  67. data/lib/uploadcare/api/rest/addons.rb +107 -0
  68. data/lib/uploadcare/api/rest/document_conversions.rb +65 -0
  69. data/lib/uploadcare/api/rest/file_metadata.rb +71 -0
  70. data/lib/uploadcare/api/rest/files.rb +112 -0
  71. data/lib/uploadcare/api/rest/groups.rb +49 -0
  72. data/lib/uploadcare/api/rest/project.rb +23 -0
  73. data/lib/uploadcare/api/rest/video_conversions.rb +52 -0
  74. data/lib/uploadcare/api/rest/webhooks.rb +74 -0
  75. data/lib/uploadcare/api/rest.rb +254 -0
  76. data/lib/uploadcare/api/upload/files.rb +313 -0
  77. data/lib/uploadcare/api/upload/groups.rb +72 -0
  78. data/lib/uploadcare/api/upload.rb +272 -0
  79. data/lib/uploadcare/client/addons_accessor.rb +85 -0
  80. data/lib/uploadcare/client/api.rb +33 -0
  81. data/lib/uploadcare/client/conversions_accessor.rb +33 -0
  82. data/lib/uploadcare/client/document_conversions_accessor.rb +41 -0
  83. data/lib/uploadcare/client/file_metadata_accessor.rb +46 -0
  84. data/lib/uploadcare/client/files_accessor.rb +82 -0
  85. data/lib/uploadcare/client/groups_accessor.rb +35 -0
  86. data/lib/uploadcare/client/project_accessor.rb +17 -0
  87. data/lib/uploadcare/client/video_conversions_accessor.rb +33 -0
  88. data/lib/uploadcare/client/webhooks_accessor.rb +42 -0
  89. data/lib/uploadcare/client.rb +127 -0
  90. data/lib/uploadcare/cname_generator.rb +68 -0
  91. data/lib/uploadcare/collections/batch_result.rb +35 -0
  92. data/lib/uploadcare/collections/paginated.rb +165 -0
  93. data/lib/uploadcare/configuration.rb +81 -0
  94. data/lib/uploadcare/exception/auth_error.rb +2 -6
  95. data/lib/uploadcare/exception/configuration_error.rb +4 -0
  96. data/lib/uploadcare/exception/conversion_error.rb +2 -6
  97. data/lib/uploadcare/exception/invalid_request_error.rb +4 -0
  98. data/lib/uploadcare/exception/multipart_upload_error.rb +4 -0
  99. data/lib/uploadcare/exception/not_found_error.rb +4 -0
  100. data/lib/uploadcare/exception/request_error.rb +2 -6
  101. data/lib/uploadcare/exception/retry_error.rb +2 -6
  102. data/lib/uploadcare/exception/throttle_error.rb +7 -11
  103. data/lib/uploadcare/exception/unknown_status_error.rb +4 -0
  104. data/lib/uploadcare/exception/upload_error.rb +4 -0
  105. data/lib/uploadcare/exception/upload_timeout_error.rb +4 -0
  106. data/lib/uploadcare/internal/authenticator.rb +101 -0
  107. data/lib/uploadcare/internal/error_handler.rb +102 -0
  108. data/lib/uploadcare/internal/signature_generator.rb +31 -0
  109. data/lib/uploadcare/internal/throttle_handler.rb +36 -0
  110. data/lib/uploadcare/internal/upload_io.rb +110 -0
  111. data/lib/uploadcare/internal/upload_params_generator.rb +86 -0
  112. data/lib/uploadcare/internal/user_agent.rb +22 -0
  113. data/lib/uploadcare/operations/multipart_upload.rb +213 -0
  114. data/lib/uploadcare/operations/upload_router.rb +162 -0
  115. data/lib/uploadcare/resources/addon_execution.rb +97 -0
  116. data/lib/uploadcare/resources/base_resource.rb +61 -0
  117. data/lib/uploadcare/resources/document_conversion.rb +81 -0
  118. data/lib/uploadcare/resources/file.rb +366 -0
  119. data/lib/uploadcare/resources/file_metadata.rb +135 -0
  120. data/lib/uploadcare/resources/group.rb +142 -0
  121. data/lib/uploadcare/resources/project.rb +26 -0
  122. data/lib/uploadcare/resources/video_conversion.rb +59 -0
  123. data/lib/uploadcare/resources/webhook.rb +85 -0
  124. data/lib/uploadcare/result.rb +85 -0
  125. data/lib/uploadcare/signed_url_generators/akamai_generator.rb +60 -56
  126. data/lib/uploadcare/signed_url_generators/base_generator.rb +15 -15
  127. data/lib/uploadcare/version.rb +7 -0
  128. data/lib/uploadcare/webhook_signature_verifier.rb +60 -0
  129. data/lib/uploadcare.rb +84 -50
  130. data/mise.toml +2 -0
  131. data/uploadcare-ruby.gemspec +8 -7
  132. metadata +102 -74
  133. data/api_examples/upload_api/put_presigned_url_x.rb +0 -8
  134. data/lib/uploadcare/api/api.rb +0 -25
  135. data/lib/uploadcare/client/addons_client.rb +0 -69
  136. data/lib/uploadcare/client/conversion/base_conversion_client.rb +0 -59
  137. data/lib/uploadcare/client/conversion/document_conversion_client.rb +0 -45
  138. data/lib/uploadcare/client/conversion/video_conversion_client.rb +0 -46
  139. data/lib/uploadcare/client/file_client.rb +0 -48
  140. data/lib/uploadcare/client/file_list_client.rb +0 -46
  141. data/lib/uploadcare/client/file_metadata_client.rb +0 -36
  142. data/lib/uploadcare/client/group_client.rb +0 -45
  143. data/lib/uploadcare/client/multipart_upload/chunks_client.rb +0 -58
  144. data/lib/uploadcare/client/multipart_upload_client.rb +0 -64
  145. data/lib/uploadcare/client/project_client.rb +0 -20
  146. data/lib/uploadcare/client/rest_client.rb +0 -77
  147. data/lib/uploadcare/client/rest_group_client.rb +0 -43
  148. data/lib/uploadcare/client/upload_client.rb +0 -46
  149. data/lib/uploadcare/client/uploader_client.rb +0 -128
  150. data/lib/uploadcare/client/webhook_client.rb +0 -49
  151. data/lib/uploadcare/concern/error_handler.rb +0 -54
  152. data/lib/uploadcare/concern/throttle_handler.rb +0 -25
  153. data/lib/uploadcare/concern/upload_error_handler.rb +0 -32
  154. data/lib/uploadcare/entity/addons.rb +0 -14
  155. data/lib/uploadcare/entity/conversion/base_converter.rb +0 -43
  156. data/lib/uploadcare/entity/conversion/document_converter.rb +0 -15
  157. data/lib/uploadcare/entity/conversion/video_converter.rb +0 -15
  158. data/lib/uploadcare/entity/decorator/paginator.rb +0 -79
  159. data/lib/uploadcare/entity/entity.rb +0 -18
  160. data/lib/uploadcare/entity/file.rb +0 -103
  161. data/lib/uploadcare/entity/file_list.rb +0 -32
  162. data/lib/uploadcare/entity/file_metadata.rb +0 -30
  163. data/lib/uploadcare/entity/group.rb +0 -49
  164. data/lib/uploadcare/entity/group_list.rb +0 -24
  165. data/lib/uploadcare/entity/project.rb +0 -13
  166. data/lib/uploadcare/entity/uploader.rb +0 -93
  167. data/lib/uploadcare/entity/webhook.rb +0 -14
  168. data/lib/uploadcare/param/authentication_header.rb +0 -37
  169. data/lib/uploadcare/param/conversion/document/processing_job_url_builder.rb +0 -39
  170. data/lib/uploadcare/param/conversion/video/processing_job_url_builder.rb +0 -64
  171. data/lib/uploadcare/param/param.rb +0 -10
  172. data/lib/uploadcare/param/secure_auth_header.rb +0 -51
  173. data/lib/uploadcare/param/simple_auth_header.rb +0 -14
  174. data/lib/uploadcare/param/upload/signature_generator.rb +0 -24
  175. data/lib/uploadcare/param/upload/upload_params_generator.rb +0 -41
  176. data/lib/uploadcare/param/user_agent.rb +0 -21
  177. data/lib/uploadcare/param/webhook_signature_verifier.rb +0 -23
  178. data/lib/uploadcare/ruby/version.rb +0 -5
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Ruby integration for Uploadcare
1
+ # Uploadcare Ruby SDK
2
2
 
3
3
  ![license](https://img.shields.io/badge/license-MIT-brightgreen.svg)
4
4
  [![Build Status][actions-img]][actions-badge]
@@ -6,883 +6,634 @@
6
6
 
7
7
  [actions-badge]: https://github.com/uploadcare/uploadcare-ruby/actions/workflows/ruby.yml
8
8
  [actions-img]: https://github.com/uploadcare/uploadcare-ruby/actions/workflows/ruby.yml/badge.svg
9
- [coverals-img]: https://coveralls.io/repos/github/uploadcare/uploadcare-ruby/badge.svg?branch=main
10
- [coverals]: https://coveralls.io/github/uploadcare/uploadcare-ruby?branch=main
11
9
  [stack-img]: https://img.shields.io/badge/tech-stack-0690fa.svg?style=flat
12
10
  [stack]: https://stackshare.io/uploadcare/stacks/
13
11
 
14
- Uploadcare Ruby integration handles uploads and further operations with files by
15
- wrapping Upload and REST APIs.
16
-
17
- * [Installation](#installation)
18
- * [Usage](#usage)
19
- * [Uploading files](#uploading-files)
20
- * [Uploading and storing a single file](#uploading-and-storing-a-single-file)
21
- * [Multiple ways to upload files](#multiple-ways-to-upload-files)
22
- * [Uploading options](#uploading-options)
23
- * [File management](#file-management)
24
- * [File](#file)
25
- * [FileList](#filelist)
26
- * [Pagination](#pagination)
27
- * [Custom File Metadata](#custom-file-metadata)
28
- * [Group](#group)
29
- * [GroupList](#grouplist)
30
- * [Webhook](#webhook)
31
- * [Add-Ons](#add-ons)
32
- * [Project](#project)
33
- * [Conversion](#conversion)
34
- * [Useful links](#useful-links)
12
+ `uploadcare-ruby` is a framework-agnostic client for the Uploadcare Upload API and REST API.
13
+
14
+ The gem is built around:
15
+
16
+ - explicit `Uploadcare::Client` instances
17
+ - client-scoped configuration for multi-account use
18
+ - a small convenience layer for common workflows
19
+ - full endpoint coverage through `client.api.rest` and `client.api.upload`
20
+
21
+ - [Requirements](#requirements)
22
+ - [Compatibility](#compatibility)
23
+ - [Installation](#installation)
24
+ - [Design](#design)
25
+ - [Quick Start](#quick-start)
26
+ - [Configuration](#configuration)
27
+ - [Multi-Account Usage](#multi-account-usage)
28
+ - [Uploads](#uploads)
29
+ - [Files](#files)
30
+ - [Groups](#groups)
31
+ - [Project](#project)
32
+ - [Metadata](#metadata)
33
+ - [Webhooks](#webhooks)
34
+ - [Add-ons](#add-ons)
35
+ - [Conversions](#conversions)
36
+ - [Secure Delivery](#secure-delivery)
37
+ - [Errors and Results](#errors-and-results)
38
+ - [Request Options](#request-options)
39
+ - [Raw API Access](#raw-api-access)
40
+ - [Examples](#examples)
41
+ - [Upgrading from v4.x](#upgrading-from-v4x)
35
42
 
36
43
  ## Requirements
37
- * ruby 3.0+
44
+
45
+ - Ruby 3.3+
38
46
 
39
47
  ## Compatibility
40
48
 
41
- Note that `uploadcare-ruby` **3.x** is not backward compatible with
42
- **[2.x](https://github.com/uploadcare/uploadcare-ruby/tree/v2.x)**.
49
+ This gem is intended for plain Ruby applications and for framework integrations built on top of it.
50
+
51
+ - Use explicit `Uploadcare::Client` instances when you need multiple accounts in one process.
52
+ - Use `Uploadcare.configure` and `Uploadcare.client` when one global default client is enough.
53
+ - Use `client.api.rest` and `client.api.upload` when you want endpoint-level parity with the official API references.
43
54
 
44
55
  ## Installation
45
56
 
46
- Add this line to your application's Gemfile:
57
+ Add the gem to your Gemfile:
47
58
 
48
59
  ```ruby
49
60
  gem "uploadcare-ruby"
50
61
  ```
51
62
 
52
- And then execute:
63
+ Then install:
53
64
 
54
- $ bundle
55
-
56
- If you use `api_struct` gem in your project, replace it with `uploadcare-api_struct`:
57
- ```ruby
58
- gem 'uploadcare-api_struct'
65
+ ```bash
66
+ bundle
59
67
  ```
60
- and run `bundle install`
61
68
 
62
- If already not, create your project in [Uploadcare dashboard](https://app.uploadcare.com/?utm_source=github&utm_medium=referral&utm_campaign=uploadcare-ruby) and copy
63
- its [API keys](https://app.uploadcare.com/projects/-/api-keys/) from there.
69
+ Set credentials with environment variables:
64
70
 
65
- Set your Uploadcare keys in config file or through environment variables:
66
71
  ```bash
67
72
  export UPLOADCARE_PUBLIC_KEY=your_public_key
68
- export UPLOADCARE_SECRET_KEY=your_private_key
73
+ export UPLOADCARE_SECRET_KEY=your_secret_key
69
74
  ```
70
75
 
71
- Or configure your app yourself if you are using different way of storing keys.
72
- Gem configuration is available in `Uploadcare.configuration`. Full list of
73
- settings can be seen in [`lib/uploadcare.rb`](lib/uploadcare.rb)
76
+ ## Design
74
77
 
75
- ```ruby
76
- # your_config_initializer_file.rb
77
- Uploadcare.config.public_key = "your_public_key"
78
- Uploadcare.config.secret_key = "your_private_key"
79
- ```
78
+ The gem has two public layers:
79
+
80
+ ### Convenience layer
80
81
 
81
- ## Usage
82
+ This is the default API you should use in applications:
82
83
 
83
- This section contains practical usage examples. Please note, everything that
84
- follows gets way more clear once you've looked through our
85
- [docs](https://uploadcare.com/docs/?utm_source=github&utm_medium=referral&utm_campaign=uploadcare-ruby)
86
- and [Upload](https://uploadcare.com/api-refs/upload-api/) and [REST](https://uploadcare.com/api-refs/rest-api/) API refs.
84
+ - `client.files`
85
+ - `client.groups`
86
+ - `client.uploads`
87
+ - `client.project`
88
+ - `client.webhooks`
89
+ - `client.file_metadata`
90
+ - `client.addons`
91
+ - `client.conversions`
87
92
 
88
- You can also find an example project [here](https://github.com/uploadcare/uploadcare-rails-example).
93
+ This layer returns resources and collections, and it raises typed exceptions on failure.
89
94
 
90
- ### Uploading files
91
- #### Uploading and storing a single file
95
+ ### Raw parity layer
92
96
 
93
- Using Uploadcare is simple, and here are the basics of handling files.
97
+ This layer mirrors Uploadcare’s REST and Upload APIs:
98
+
99
+ - `client.api.rest`
100
+ - `client.api.upload`
101
+
102
+ This layer returns `Uploadcare::Result` objects so you can inspect success and failure explicitly.
103
+
104
+ That split keeps app code clean without losing full API coverage.
105
+
106
+ ## Quick Start
94
107
 
95
108
  ```ruby
96
- @file_to_upload = File.open("your-file.png")
109
+ require "uploadcare"
97
110
 
98
- @uc_file = Uploadcare::Uploader.upload(@file_to_upload, store: "auto")
111
+ client = Uploadcare::Client.new(
112
+ public_key: ENV.fetch("UPLOADCARE_PUBLIC_KEY"),
113
+ secret_key: ENV.fetch("UPLOADCARE_SECRET_KEY")
114
+ )
99
115
 
100
- @uc_file.uuid
101
- # => "dc99200d-9bd6-4b43-bfa9-aa7bfaefca40"
116
+ file = File.open("photo.jpg", "rb") do |io|
117
+ client.files.upload(io, store: true)
118
+ end
102
119
 
103
- # URL for the file, can be used with your website or app right away
104
- @uc_file.original_file_url
105
- # => "https://ucarecdn.com/dc99200d-9bd6-4b43-bfa9-aa7bfaefca40/your-file.png"
120
+ puts file.uuid
121
+ puts file.cdn_url
106
122
  ```
107
123
 
108
- The `store` option can have these possible values:
109
- - `true`: mark the uploaded file as stored.
110
- - `false`: do not mark the uploaded file as stored and remove it after 24 hours.
111
- - `"auto"`: defers the choice of storage behavior to the [auto-store setting](https://app.uploadcare.com/projects/-/settings/#storage) for your Uploadcare project. This is the default behavior.
112
-
113
- Your might then want to store or delete the uploaded file.
124
+ You can also configure a default global client:
114
125
 
115
126
  ```ruby
116
- # that's how you store a file, if you have uploaded the file using store: false and changed your mind later
117
- @uc_file.store
118
- # => #<Uploadcare::Api::File ...
127
+ Uploadcare.configure do |config|
128
+ config.public_key = ENV.fetch("UPLOADCARE_PUBLIC_KEY")
129
+ config.secret_key = ENV.fetch("UPLOADCARE_SECRET_KEY")
130
+ end
119
131
 
120
- # and that works for deleting it
121
- @uc_file.delete
122
- # => #<Uploadcare::Api::File ...
132
+ file = File.open("photo.jpg", "rb") do |io|
133
+ Uploadcare.files.upload(io, store: true)
134
+ end
123
135
  ```
124
136
 
125
- #### Multiple ways to upload files
137
+ The recommended style is explicit `Uploadcare::Client` instances. Global configuration is best treated as a default.
126
138
 
127
- Uploadcare supports multiple ways to upload files:
139
+ ## Example Usage
140
+
141
+ This is the shortest end-to-end flow for the main public API:
128
142
 
129
143
  ```ruby
130
- # Smart upload - detects type of passed object and picks appropriate upload method
131
- # If you have a large file (more than 100Mb / 10485760 bytes), the uploader will automatically process it with a multipart upload
144
+ require "uploadcare"
132
145
 
133
- Uploadcare::Uploader.upload("https://placekitten.com/96/139", store: "auto")
134
- ```
146
+ client = Uploadcare::Client.new(
147
+ public_key: ENV.fetch("UPLOADCARE_PUBLIC_KEY"),
148
+ secret_key: ENV.fetch("UPLOADCARE_SECRET_KEY")
149
+ )
135
150
 
136
- There are explicit ways to select upload type:
151
+ file = File.open("photo.jpg", "rb") do |io|
152
+ client.files.upload(io, store: true)
153
+ end
137
154
 
138
- ```ruby
139
- files = [File.open("1.jpg"), File.open("1.jpg")]
140
- Uploadcare::Uploader.upload_files(files, store: 'auto')
155
+ group = client.groups.create(uuids: [file.uuid])
141
156
 
142
- Uploadcare::Uploader.upload_from_url("https://placekitten.com/96/139", store: "auto")
157
+ puts file.uuid
158
+ puts file.cdn_url
159
+ puts group.id
160
+ puts group.cdn_url
143
161
  ```
144
- It is possible to track progress of the upload-from-URL process. To do that, you should specify the `async` option and get a token:
145
162
 
146
- ```ruby
147
- Uploadcare::Uploader.upload_from_url("https://placekitten.com/96/139", async: true)
148
- # => "c6e31082-6bdc-4cb3-bef5-14dd10574d72"
149
- ```
163
+ ## Configuration
150
164
 
151
- After the request for uploading-from-URL is sent, you can check the progress of the upload by sending the `get_upload_from_url_status` request:
165
+ Use `Uploadcare.configure` to set process-wide defaults:
152
166
 
153
167
  ```ruby
154
- Uploadcare::Uploader.get_upload_from_url_status("1251ee66-3631-4416-a2fb-96ba59f5a515")
155
- # => Success({:size=>453543, :total=>453543, :done=>453543, :uuid=>"5c51a7fe-e45d-42a2-ba5e-79957ff4bdab", :file_id=>"5c51a7fe-e45d-42a2-ba5e-79957ff4bdab", :original_filename=>"2250", :is_image=>true, :is_stored=>false, :image_info=>{:dpi=>[96, 96], :width=>2250, :format=>"JPEG", :height=>2250, :sequence=>false, :color_mode=>"RGB", :orientation=>nil, :geo_location=>nil, :datetime_original=>nil}, :video_info=>nil, :content_info=>{:mime=>{:mime=>"image/jpeg", :type=>"image", :subtype=>"jpeg"}, :image=>{:dpi=>[96, 96], :width=>2250, :format=>"JPEG", :height=>2250, :sequence=>false, :color_mode=>"RGB", :orientation=>nil, :geo_location=>nil, :datetime_original=>nil}}, :is_ready=>true, :filename=>"2250", :mime_type=>"image/jpeg", :metadata=>{}, :status=>"success"})
168
+ Uploadcare.configure do |config|
169
+ config.public_key = "public_key"
170
+ config.secret_key = "secret_key"
171
+ config.auth_type = "Uploadcare"
172
+ config.use_subdomains = false
173
+ end
156
174
  ```
157
175
 
158
- In case of the `async` option is disabled, uploadcare-ruby tries to request the upload status several times (depending on the `max_request_tries` config param) and then returns uploaded file attributes.
176
+ Or build configuration objects directly:
159
177
 
160
178
  ```ruby
161
- # multipart upload - can be useful for files bigger than 10 mb
162
- Uploadcare::Uploader.multipart_upload(File.open("big_file.bin"), store: true)
179
+ base_config = Uploadcare::Configuration.new(
180
+ public_key: "public_key",
181
+ secret_key: "secret_key"
182
+ )
183
+
184
+ client = Uploadcare::Client.new(config: base_config)
163
185
  ```
164
186
 
165
- For the multipart upload you can pass a block to add some additional logic after each file chunk is uploaded.
166
- For example to track file uploading progress you can do something like this:
187
+ Configuration objects are copyable:
167
188
 
168
189
  ```ruby
169
- file = File.open("big_file.bin")
170
- progress = 0
171
- Uploadcare::Uploader.multipart_upload(file, store: true) do |options|
172
- progress += (100.0 / options[:links_count])
173
- puts "PROGRESS = #{progress}"
174
- end
175
- ```
176
- Output of the code above looks like:
177
- ```console
178
- PROGRESS = 4.545454545454546
179
- PROGRESS = 9.090909090909092
180
- PROGRESS = 13.636363636363637
181
- ...
182
- ```
183
- Options available in a block:
184
- - **:chunk_size** - size of each chunk in bytes;
185
- - **:object** - file object which is going to be uploaded;
186
- - **:offset** - offset from the beginning of a File object in bytes;
187
- - **:link_id** - index of a link provided by Uploadcare API. Might be treated as index of a chunk;
188
- - **:links** - array of links for uploading file's chunks;
189
- - **:links_count** - count of the array of links.
190
-
191
- #### Uploading options
192
-
193
- You can override [auto-store setting](https://app.uploadcare.com/projects/-/settings/#storage) from your Uploadcare project for each upload request:
194
-
195
- ```ruby
196
- @api.upload(files, store: true) # mark the uploaded file as stored.
197
- @api.upload(files, store: false) # do not mark the uploaded file as stored and remove it after 24 hours.
198
- @api.upload_from_url(url, store: "auto") # defers the choice of storage behavior to the auto-store setting.
199
- ```
200
-
201
- You can upload file with custom metadata, for example `subsystem` and `pet`:
202
-
203
- ```ruby
204
- @api.upload(files, metadata: { subsystem: 'my_subsystem', pet: 'cat' } )
205
- @api.upload_from_url(url, metadata: { subsystem: 'my_subsystem', pet: 'cat' })
206
- ```
207
-
208
- ### File management
209
-
210
- Entities are representations of objects in Uploadcare cloud.
211
-
212
- #### File
213
-
214
- File entity contains its metadata. It also supports `include` param to include additional fields to the file object, such as: "appdata".
215
-
216
- ```ruby
217
- @file = Uploadcare::File.file("FILE_UUID", include: "appdata")
218
- {
219
- "datetime_removed"=>nil,
220
- "datetime_stored"=>"2018-11-26T12:49:10.477888Z",
221
- "datetime_uploaded"=>"2018-11-26T12:49:09.945335Z",
222
- "is_image"=>true,
223
- "is_ready"=>true,
224
- "mime_type"=>"image/jpeg",
225
- "original_file_url"=>"https://ucarecdn.com/FILE_UUID/pineapple.jpg",
226
- "original_filename"=>"pineapple.jpg",
227
- "size"=>642,
228
- "url"=>"https://api.uploadcare.com/files/FILE_UUID/",
229
- "uuid"=>"FILE_UUID",
230
- "variations"=>nil,
231
- "content_info"=>{
232
- "mime"=>{
233
- "mime"=>"image/jpeg",
234
- "type"=>"image",
235
- "subtype"=>"jpeg"
236
- },
237
- "image"=>{
238
- "format"=>"JPEG",
239
- "width"=>500,
240
- "height"=>500,
241
- "sequence"=>false,
242
- "orientation"=>6,
243
- "geo_location"=>{
244
- "latitude"=>55.62013611111111,
245
- "longitude"=>37.66299166666666
246
- },
247
- "datetime_original"=>"2018-08-20T08:59:50",
248
- "dpi"=>[72, 72]
249
- }
250
- },
251
- "metadata"=>{
252
- "subsystem"=>"uploader",
253
- "pet"=>"cat"
254
- },
255
- "appdata"=>{
256
- "uc_clamav_virus_scan"=>{
257
- "data"=>{
258
- "infected"=>true,
259
- "infected_with"=>"Win.Test.EICAR_HDB-1"
260
- },
261
- "version"=>"0.104.2",
262
- "datetime_created"=>"2021-09-21T11:24:33.159663Z",
263
- "datetime_updated"=>"2021-09-21T11:24:33.159663Z"
264
- },
265
- "remove_bg"=>{
266
- "data"=>{
267
- "foreground_type"=>"person"
268
- },
269
- "version"=>"1.0",
270
- "datetime_created"=>"2021-07-25T12:24:33.159663Z",
271
- "datetime_updated"=>"2021-07-25T12:24:33.159663Z"
272
- },
273
- "aws_rekognition_detect_labels"=>{
274
- "data"=>{
275
- "LabelModelVersion"=>"2.0",
276
- "Labels"=>[
277
- {
278
- "Confidence"=>93.41645812988281,
279
- "Instances"=>[],
280
- "Name"=>"Home Decor",
281
- "Parents"=>[]
282
- },
283
- {
284
- "Confidence"=>70.75951385498047,
285
- "Instances"=>[],
286
- "Name"=>"Linen",
287
- "Parents"=>[{ "Name"=>"Home Decor" }]
288
- },
289
- {
290
- "Confidence"=>64.7123794555664,
291
- "Instances"=>[],
292
- "Name"=>"Sunlight",
293
- "Parents"=>[]
294
- },
295
- {
296
- "Confidence"=>56.264793395996094,
297
- "Instances"=>[],
298
- "Name"=>"Flare",
299
- "Parents"=>[{ "Name"=>"Light" }]
300
- },
301
- {
302
- "Confidence"=>50.47153854370117,
303
- "Instances"=>[],
304
- "Name"=>"Tree",
305
- "Parents"=>[{ "Name"=>"Plant" }]
306
- }
307
- ]
308
- },
309
- "version"=>"2016-06-27",
310
- "datetime_created"=>"2021-09-21T11:25:31.259763Z",
311
- "datetime_updated"=>"2021-09-21T11:27:33.359763Z"
312
- }
313
- }
314
- }
315
-
316
- @file.local_copy # copy file to local storage
317
-
318
- @file.remote_copy # copy file to remote storage
319
-
320
- @file.store # stores file, returns updated metadata
321
-
322
- @file.delete #deletes file. Returns updated metadata
323
- ```
324
-
325
- The File object is also can be converted if it is a document or a video file. Imagine, you have a document file:
326
-
327
- ```ruby
328
- @file = Uploadcare::File.file("FILE_UUID")
329
- ```
330
-
331
- To convert it to an another file, just do:
332
-
333
- ```ruby
334
- @converted_file = @file.convert_document({ format: "png", page: "1" }, store: true)
335
- # => {
336
- # "uuid"=>"<NEW_FILE_UUID>"}
337
- # ...other file info...
338
- # }
339
- # OR
340
- # Failure({:"<FILE_UUID>/document/-/format/png/-/page/1/"=>"the target_format is not a supported 'to' format for this source file. <you_source_file_extension> -> png"})
341
- ```
342
-
343
- Same works for video files:
344
-
345
- ```ruby
346
- @converted_file = @file.convert_video(
347
- {
348
- format: "ogg",
349
- quality: "best",
350
- cut: { start_time: "0:0:0.1", length: "end" },
351
- size: { resize_mode: "change_ratio", width: "600", height: "400" },
352
- thumb: { N: 1, number: 2 }
353
- },
354
- store: true
355
- )
356
- # => {
357
- # "uuid"=>"<NEW_FILE_UUID>"}
358
- # ...other file info...
359
- # }
360
- # OR
361
- # Failure({:"<FILE_UUID>/video/-/size/600x400/preserve_ratio/-/quality/best/-/format/ogg/-/cut/0:0:0.1/end/-/thumbs~1/2/"=>"CDN Path error: Failed to parse remainder \"/preserve_ratio\" of \"size/600x400/preserve_ratio\""})
190
+ account_a = Uploadcare::Client.new(config: base_config.with(public_key: "pk-a", secret_key: "sk-a"))
191
+ account_b = Uploadcare::Client.new(config: base_config.with(public_key: "pk-b", secret_key: "sk-b"))
362
192
  ```
363
193
 
364
- More about file conversion [here](#conversion).
365
- Metadata of deleted files is stored permanently.
194
+ Common configuration options:
366
195
 
367
- #### FileList
196
+ - `public_key`
197
+ - `secret_key`
198
+ - `auth_type`
199
+ - `multipart_size_threshold`
200
+ - `multipart_chunk_size`
201
+ - `upload_threads`
202
+ - `upload_timeout`
203
+ - `max_upload_retries`
204
+ - `sign_uploads`
205
+ - `upload_signature_lifetime`
206
+ - `use_subdomains`
207
+ - `cdn_base_postfix`
208
+ - `default_cdn_base`
368
209
 
369
- `Uploadcare::FileList` represents the whole collection of files (or it's
370
- subset) and provides a way to iterate through it, making pagination transparent.
371
- FileList objects can be created using `Uploadcare::FileList.file_list` method.
210
+ CDN helpers:
372
211
 
373
212
  ```ruby
374
- @list = Uploadcare::FileList.file_list
375
- # Returns instance of Uploadcare::Entity::FileList
376
- <Hashie::Mash
377
- next=nil
378
- per_page=100
379
- previous=nil
380
- results=[
381
- # Array of Entity::File
382
- ]
383
- total=8>
384
- # load last page of files
385
- @files = @list.files
386
- # load all files
387
- @all_files = @list.load
388
- ```
213
+ Uploadcare.configure do |config|
214
+ config.use_subdomains = true
215
+ config.cdn_base_postfix = "https://ucarecd.net/"
216
+ config.default_cdn_base = "https://ucarecdn.com/"
217
+ end
389
218
 
390
- This method accepts some options to control which files should be fetched and
391
- how they should be fetched:
219
+ Uploadcare.configuration.custom_cname
220
+ Uploadcare.configuration.cdn_base
221
+ ```
392
222
 
393
- - **:limit** — Controls page size. Accepts values from 1 to 1000, defaults to 100.
394
- - **:stored** — Can be either `true` or `false`. When true, file list will contain only stored files. When false — only not stored.
395
- - **:removed** — Can be either `true` or `false`. When true, file list will contain only removed files. When false — all except removed. Defaults to false.
396
- - **:ordering** — Controls the order of returned files. Available values: `datetime_uploaded`, `-datetime_uploaded`. Defaults to `datetime_uploaded`. More info can be found [here](https://uploadcare.com/api-refs/rest-api/v0.7.0/#operation/filesList).
397
- - **:from** — Specifies the starting point for a collection. Resulting collection will contain files from the given value and to the end in a direction set by an **ordering** option. When files are ordered by `datetime_updated` in any direction, accepts either a `DateTime` object or an ISO 8601 string. When files are ordered by size, accepts non-negative integers (size in bytes). More info can be found [here](https://uploadcare.com/api-refs/rest-api/v0.7.0/#operation/filesList).
223
+ ## Multi-Account Usage
398
224
 
399
- Options used to create a file list can be accessed through `#options` method.
400
- Note that, once set, they don't affect file fetching process anymore and are
401
- stored just for your convenience. That is why they are frozen.
225
+ The gem is designed to support multiple Uploadcare projects in the same process:
402
226
 
403
227
  ```ruby
404
- options = {
405
- limit: 10,
406
- stored: true,
407
- ordering: "-datetime_uploaded",
408
- from: "2017-01-01T00:00:00",
409
- }
410
- @list = @api.file_list(options)
228
+ primary = Uploadcare::Client.new(public_key: "pk-1", secret_key: "sk-1")
229
+ secondary = Uploadcare::Client.new(public_key: "pk-2", secret_key: "sk-2")
230
+
231
+ primary_file = primary.files.find(uuid: "uuid-1")
232
+ secondary_file = secondary.files.find(uuid: "uuid-2")
411
233
  ```
412
234
 
413
- To simply get all associated objects:
235
+ You can also derive temporary variants from an existing client:
236
+
414
237
  ```ruby
415
- @list.all # => returns Array of Files
238
+ admin_client = primary.with(secret_key: "different-secret")
416
239
  ```
417
240
 
418
- #### Pagination
241
+ Resource objects retain their client context, so subsequent instance operations stay bound to the correct account.
242
+
243
+ ## Uploads
244
+
245
+ ### Smart upload
246
+
247
+ `client.uploads.upload` accepts:
248
+
249
+ - an IO or file object
250
+ - an array of IO or file objects
251
+ - an HTTP or HTTPS URL string
419
252
 
420
- Initially, `FileList` is a paginated collection. It can be navigated using following methods:
421
253
  ```ruby
422
- @file_list = Uploadcare::FileList.file_list
423
- # Let's assume there are 250 files in cloud. By default, UC loads 100 files. To get next 100 files, do:
424
- @next_page = @file_list.next_page
425
- # To get previous page:
426
- @previous_page = @file_list.previous_page
254
+ file = File.open("photo.jpg", "rb") do |io|
255
+ client.uploads.upload(io, store: true)
256
+ end
257
+
258
+ remote_file = client.uploads.upload("https://example.com/image.jpg", store: true)
427
259
  ```
428
260
 
429
- Alternatively, it's possible to iterate through full list of groups or files with `each`:
261
+ ### Single file upload
262
+
430
263
  ```ruby
431
- @list.each do |file|
432
- p file.url
264
+ file = File.open("photo.jpg", "rb") do |io|
265
+ client.files.upload(io, store: true, metadata: { subsystem: "avatars" })
433
266
  end
434
267
  ```
435
268
 
436
- #### Custom File Metadata
437
-
438
- File metadata is additional, arbitrary data, associated with uploaded file.
439
- As an example, you could store unique file identifier from your system.
269
+ ### Multiple file upload
440
270
 
441
271
  ```ruby
442
- # Get file's metadata keys and values.
443
- Uploadcare::FileMetadata.index('FILE_UUID')
444
-
445
- # Get the value of a single metadata key.
446
- Uploadcare::FileMetadata.show('FILE_UUID', 'KEY')
272
+ files = [
273
+ File.open("photo-1.jpg", "rb"),
274
+ File.open("photo-2.jpg", "rb")
275
+ ]
447
276
 
448
- # Update the value of a single metadata key. If the key does not exist, it will be created.
449
- Uploadcare::FileMetadata.update('FILE_UUID', 'KEY', 'VALUE')
277
+ uploaded = client.uploads.upload(files, store: true)
450
278
 
451
- # Delete a file's metadata key.
452
- Uploadcare::FileMetadata.delete('FILE_UUID', 'KEY')
279
+ files.each(&:close)
453
280
  ```
454
281
 
455
- #### Group
282
+ ### Upload from URL
456
283
 
457
- Groups are structures intended to organize sets of separate files. Each group is
458
- assigned UUID. Note, group UUIDs include a `~#{files_count}` part at the end.
459
- That's a requirement of our API.
284
+ Synchronous:
460
285
 
461
286
  ```ruby
462
- # group can be created from an array of Uploadcare files (UUIDs)
463
- @file = "134dc30c-093e-4f48-a5b9-966fe9cb1d01"
464
- @file2 = "134dc30c-093e-4f48-a5b9-966fe9cb1d02"
465
- @files_ary = [@file, @file2]
466
- @group = Uploadcare::Group.create @files
467
-
468
- # group can be stored by group ID. It means that all files of a group will be stored on Uploadcare servers permanently
469
- Uploadcare::Group.store(group.id)
287
+ file = client.files.upload_from_url("https://example.com/image.jpg", store: true)
288
+ ```
470
289
 
471
- # get a file group by its ID.
472
- Uploadcare::Group.rest_info(group.id)
290
+ Async:
473
291
 
474
- # group can be deleted by group ID.
475
- Uploadcare::Group.delete(group.id)
476
- # Note: This operation only removes the group object itself. All the files that were part of the group are left as is.
292
+ ```ruby
293
+ job = client.uploads.upload_from_url(url: "https://example.com/image.jpg", async: true, store: true)
294
+ status = client.uploads.upload_from_url_status(token: job.fetch("token"))
477
295
  ```
478
296
 
479
- #### GroupList
480
- `GroupList` is a list of `Group`
297
+ When async mode is enabled, the convenience layer returns the raw status token hash because the file does not exist yet.
298
+
299
+ Polling options for synchronous URL uploads:
300
+
301
+ - `poll_interval` (default: `1`) initial status polling interval in seconds
302
+ - `poll_max_interval` (default: `10`) maximum polling interval in seconds
303
+ - `poll_timeout` (default: `300`) maximum total polling time in seconds
304
+
305
+ ### Multipart upload with progress
481
306
 
482
307
  ```ruby
483
- @group_list = Uploadcare::GroupList.list
484
- # To get an array of groups:
485
- @groups = @group_list.all
308
+ File.open("large-video.mp4", "rb") do |io|
309
+ file = client.uploads.multipart_upload(file: io, store: true, threads: 4) do |progress|
310
+ uploaded = progress[:uploaded]
311
+ total = progress[:total]
312
+ puts "#{uploaded}/#{total}"
313
+ end
314
+
315
+ puts file.uuid
316
+ end
486
317
  ```
487
318
 
488
- This is a paginated list, so [pagination](#Pagination) methods apply
319
+ ### Signed uploads
489
320
 
490
- #### Webhook
491
- https://uploadcare.com/docs/api_reference/rest/webhooks/
321
+ You can enable signed uploads globally:
492
322
 
493
- You can use webhooks to provide notifications about your uploads to target urls.
494
- This gem lets you create and manage webhooks.
323
+ ```ruby
324
+ client = Uploadcare::Client.new(
325
+ public_key: "public",
326
+ secret_key: "secret",
327
+ sign_uploads: true
328
+ )
329
+ ```
495
330
 
496
- Each webhook payload can be signed with a secret (the `signing_secret` option) to ensure that the request comes from the expected sender.
497
- More info about secure webhooks [here](https://uploadcare.com/docs/security/secure-webhooks/).
331
+ Or pass explicit signature data per request:
498
332
 
499
333
  ```ruby
500
- Uploadcare::Webhook.create(target_url: "https://example.com/listen", event: "file.uploaded", is_active: true, signing_secret: "some-secret")
501
- Uploadcare::Webhook.update(<webhook_id>, target_url: "https://newexample.com/listen/new", event: "file.uploaded", is_active: true, signing_secret: "some-secret")
502
- Uploadcare::Webhook.delete("https://example.com/listen")
503
- Uploadcare::Webhook.list
334
+ File.open("photo.jpg", "rb") do |io|
335
+ client.files.upload(io, signature: "signature", expire: 1_900_000_000)
336
+ end
504
337
  ```
505
338
 
506
- ##### Webhook signature verification
339
+ ### Upload options
507
340
 
508
- The gem has a helper class to verify a webhook signature from headers —
509
- `Uploadcare::Param::WebhookSignatureVerifier`. This class accepts three
510
- important options:
341
+ Common upload options:
511
342
 
512
- - **:webhook_body** this option represents parameters received in the webhook
513
- request in the JSON format.
514
- **NOTE**: if you're using Rails, you should exclude options `controller`,
515
- `action` and `post` from the `webhook_body`.
516
- - **:signing_secret** the secret that was set while creating/updating a
517
- webhook. This option can be specified as an ENV var with the name
518
- `UC_SIGNING_SECRET` — then no need to send it to the verifier class.
519
- - **:x_uc_signature_header** — the content of the `X-Uc-Signature` HTTP header
520
- in the webhook request.
343
+ - `store: true | false | "auto"`
344
+ - `metadata: { key: value }`
345
+ - `signature: "..."`
346
+ - `expire: unix_timestamp`
347
+ - `async: true` for URL uploads
348
+ - `threads:` and `part_size:` for multipart uploads
521
349
 
522
- Using the `Uploadcare::Param::WebhookSignatureVerifier` class example:
350
+ If you prefer the older top-level style, the same flows can still be written through the global client:
523
351
 
524
352
  ```ruby
525
- webhook_body = '{...}'
353
+ Uploadcare.configure do |config|
354
+ config.public_key = ENV.fetch("UPLOADCARE_PUBLIC_KEY")
355
+ config.secret_key = ENV.fetch("UPLOADCARE_SECRET_KEY")
356
+ end
357
+
358
+ file = File.open("photo.jpg", "rb") do |io|
359
+ Uploadcare.files.upload(io, store: true)
360
+ end
361
+ ```
526
362
 
527
- signing_secret = "12345X"
528
- x_uc_signature_header = "v1=9b31c7dd83fdbf4a2e12b19d7f2b9d87d547672a325b9492457292db4f513c70"
363
+ ## Files
529
364
 
530
- Uploadcare::Param::WebhookSignatureVerifier.valid?(signing_secret: signing_secret, x_uc_signature_header: x_uc_signature_header, webhook_body: webhook_body)
365
+ ### Find a file
366
+
367
+ ```ruby
368
+ file = client.files.find(uuid: "file-uuid")
531
369
  ```
532
370
 
533
- You can write your verifier. Example code:
371
+ ### List files
534
372
 
535
373
  ```ruby
536
- webhook_body_json = '{...}'
374
+ files = client.files.list(limit: 100)
375
+ files.each { |file| puts file.uuid }
376
+ ```
537
377
 
538
- signing_secret = ENV['UC_SIGNING_SECRET']
539
- x_uc_signature_header = "v1=f4d859ed2fe47b9a4fcc81693d34e58ad12366a841e58a7072c1530483689cc0"
378
+ List responses are `Uploadcare::Collections::Paginated`:
540
379
 
541
- digest = OpenSSL::Digest.new('sha256')
380
+ ```ruby
381
+ files.next_page
382
+ files.previous_page
383
+ files.all
384
+ ```
542
385
 
543
- calculated_signature = "v1=#{OpenSSL::HMAC.hexdigest(digest, signing_secret.force_encoding("utf-8"), webhook_body_json.force_encoding("utf-8"))}"
386
+ Filters and API parameters can still be passed through:
544
387
 
545
- if calculated_signature == x_uc_signature_header
546
- puts "WebHook signature matches!"
547
- else
548
- puts "WebHook signature mismatch!"
549
- end
388
+ ```ruby
389
+ files = client.files.list(stored: true, removed: false, limit: 100)
550
390
  ```
551
391
 
552
- #### Add-Ons
392
+ ### Resource operations
553
393
 
554
- An `Add-On` is an application implemented by Uploadcare that accepts uploaded files as an input and can produce other files and/or appdata as an output.
394
+ ```ruby
395
+ file.store
396
+ file.delete
397
+ file.reload
398
+ file.reload(params: { include: "appdata" })
399
+ ```
555
400
 
556
- ##### AWS Rekognition
401
+ ### Batch operations
557
402
 
558
403
  ```ruby
559
- # Execute AWS Rekognition Add-On for a given target to detect labels in an image.
560
- # Note: Detected labels are stored in the file's appdata.
561
- Uploadcare::Addons.ws_rekognition_detect_labels('FILE_UUID')
404
+ result = client.files.batch_store(uuids: ["uuid-1", "uuid-2"])
562
405
 
563
- # Check the status of AWS Rekognition.
564
- Uploadcare::Addons.ws_rekognition_detect_labels_status('RETURNED_ID_FROM_WS_REKOGNITION_DETECT_LABELS')
406
+ puts result.status
407
+ puts result.result.map(&:uuid)
408
+ puts result.problems
565
409
  ```
566
410
 
567
- ##### AWS Rekognition Moderation
411
+ The same shape applies to `client.files.batch_delete`.
412
+
413
+ ### Copy operations
568
414
 
569
415
  ```ruby
570
- # Execute AWS Rekognition Moderation Add-On for a given target to detect moderation labels in an image.
571
- # Note: Detected moderation labels are stored in the file's appdata.
416
+ copied = client.files.copy_to_local(source: file.uuid, options: { store: true })
417
+ remote_url = client.files.copy_to_remote(source: file.uuid, target: "custom_storage")
418
+ ```
572
419
 
573
- Uploadcare::Addons.ws_rekognition_detect_moderation_labels('FILE_UUID')
420
+ Instance-level variants are also available:
574
421
 
575
- # Check the status of an Add-On execution request that had been started using the Execute Add-On operation.
576
- Uploadcare::Addons.ws_rekognition_detect_moderation_labels_status('RETURNED_ID_FROM_WS_REKOGNITION_DETECT_MODERATION_LABELS')
422
+ ```ruby
423
+ copied = file.copy_to_local(options: { store: true })
424
+ remote_url = file.copy_to_remote(target: "custom_storage")
577
425
  ```
578
426
 
579
- ##### ClamAV
427
+ ## Groups
428
+
429
+ Create a group:
580
430
 
581
431
  ```ruby
582
- # ClamAV virus checking Add-On for a given target.
583
- Uploadcare::Addons.uc_clamav_virus_scan('FILE_UUID')
432
+ group = client.groups.create(uuids: ["uuid-1", "uuid-2"])
433
+ ```
584
434
 
585
- # Check and purge infected file.
586
- Uploadcare::Addons.uc_clamav_virus_scan('FILE_UUID', purge_infected: true )
435
+ Find and list groups:
587
436
 
588
- # Check the status of an Add-On execution request that had been started using the Execute Add-On operation.
589
- Uploadcare::Addons.uc_clamav_virus_scan_status('RETURNED_ID_FROM_UC_CLAMAV_VIRUS_SCAN')
437
+ ```ruby
438
+ group = client.groups.find(group_id: "group-uuid~2")
439
+ groups = client.groups.list(limit: 50)
590
440
  ```
591
441
 
592
- ##### Remove.bg
442
+ Delete a group:
593
443
 
594
444
  ```ruby
595
- # Execute remove.bg background image removal Add-On for a given target.
596
- Uploadcare::Addons.remove_bg('FILE_UUID')
445
+ group.delete
446
+ ```
597
447
 
598
- # You can pass optional parameters.
599
- # See the full list of parameters here: https://uploadcare.com/api-refs/rest-api/v0.7.0/#operation/removeBgExecute
600
- Uploadcare::Addons.remove_bg('FILE_UUID', crop: true, type_level: '2')
448
+ Useful group helpers:
601
449
 
602
- # Check the status of an Add-On execution request that had been started using the Execute Add-On operation.
603
- Uploadcare::Addons.remove_bg_status('RETURNED_ID_FROM_REMOVE_BG')
450
+ ```ruby
451
+ group.cdn_url
452
+ group.file_cdn_urls
604
453
  ```
605
454
 
606
- #### Project
455
+ ## Project
607
456
 
608
- `Project` provides basic info about the connected Uploadcare project. That
609
- object is also an Hashie::Mash, so every methods out of
610
- [these](https://uploadcare.com/api-refs/rest-api/v0.7.0/#operation/projectInfo) will work.
457
+ Fetch the current project:
611
458
 
612
459
  ```ruby
613
- @project = Uploadcare::Project.project
614
- # => #<Uploadcare::Api::Project collaborators=[], name="demo", pub_key="your_public_key", autostore_enabled=true>
615
-
616
- @project.name
617
- # => "demo"
460
+ project = client.project.current
618
461
 
619
- @project.collaborators
620
- # => []
621
- # while that one was empty, it usually goes like this:
622
- # [{"email": collaborator@gmail.com, "name": "Collaborator"}, {"email": collaborator@gmail.com, "name": "Collaborator"}]
462
+ puts project.name
463
+ puts project.pub_key
464
+ puts project.collaborators
623
465
  ```
624
466
 
625
- #### Conversion
467
+ ## Metadata
626
468
 
627
- ##### Video
469
+ ```ruby
470
+ client.file_metadata.update(uuid: file.uuid, key: "category", value: "avatar")
471
+ client.file_metadata.show(uuid: file.uuid, key: "category")
472
+ client.file_metadata.index(uuid: file.uuid)
473
+ client.file_metadata.delete(uuid: file.uuid, key: "category")
474
+ ```
628
475
 
629
- After each video file upload you obtain a file identifier in UUID format.
630
- Then you can use this file identifier to convert your video in multiple ways:
476
+ `Uploadcare::FileMetadata` is also available as a resource if you need to hold metadata state locally.
477
+
478
+ ## Webhooks
631
479
 
632
480
  ```ruby
633
- Uploadcare::VideoConverter.convert(
634
- [
635
- {
636
- uuid: "dc99200d-9bd6-4b43-bfa9-aa7bfaefca40",
637
- size: { resize_mode: "change_ratio", width: "600", height: "400" },
638
- quality: "best",
639
- format: "ogg",
640
- cut: { start_time: "0:0:0.0", length: "0:0:1.0" },
641
- thumbs: { N: 2, number: 1 }
642
- }
643
- ],
644
- store: false
481
+ webhook = client.webhooks.create(
482
+ target_url: "https://example.com/uploadcare",
483
+ event: "file.uploaded",
484
+ is_active: true
645
485
  )
486
+
487
+ client.webhooks.list
488
+ client.webhooks.update(id: webhook.id, is_active: false)
489
+ client.webhooks.delete(target_url: webhook.target_url)
646
490
  ```
647
- This method accepts options to set properties of an output file:
648
-
649
- - **uuid** — the file UUID-identifier.
650
- - **size**:
651
- - **resize_mode** - size operation to apply to a video file. Can be `preserve_ratio (default)`, `change_ratio`, `scale_crop` or `add_padding`.
652
- - **width** - width for a converted video.
653
- - **height** - height for a converted video.
654
-
655
- ```
656
- NOTE: you can choose to provide a single dimension (width OR height).
657
- The value you specify for any of the dimensions should be a non-zero integer divisible by 4
658
- ```
659
-
660
- - **quality** - sets the level of video quality that affects file sizes and hence loading times and volumes of generated traffic. Can be `normal (default)`, `better`, `best`, `lighter`, `lightest`.
661
- - **format** - format for a converted video. Can be `mp4 (default)`, `webm`, `ogg`.
662
- - **cut**:
663
- - **start_time** - defines the starting point of a fragment to cut based on your input file timeline.
664
- - **length** - defines the duration of that fragment.
665
- - **thumbs**:
666
- - **N** - quantity of thumbnails for your video - non-zero integer ranging from 1 to 50; defaults to 1.
667
- - **number** - zero-based index of a particular thumbnail in a created set, ranging from 1 to (N - 1).
668
- - **store** - a flag indicating if Uploadcare should store your transformed outputs.
669
-
670
- ```ruby
671
- # Response
672
- {
673
- :result => [
674
- {
675
- :original_source=>"dc99200d-9bd6-4b43-bfa9-aa7bfaefca40/video/-/size/600x400/change_ratio/-/quality/best/-/format/ogg/-/cut/0:0:0.0/0:0:1.0/-/thumbs~2/1/",
676
- :token=>911933811,
677
- :uuid=>"6f9b88bd-625c-4d60-bfde-145fa3813d95",
678
- :thumbnails_group_uuid=>"cf34c5a1-8fcc-4db2-9ec5-62c389e84468~2"
679
- }
680
- ],
681
- :problems=>{}
682
- }
683
- ```
684
- Params in the response:
685
- - **result** - info related to your transformed output(-s):
686
- - **original_source** - built path for a particular video with all the conversion operations and parameters.
687
- - **token** - a processing job token that can be used to get a [job status](https://uploadcare.com/docs/transformations/video-encoding/#status) (see below).
688
- - **uuid** - UUID of your processed video file.
689
- - **thumbnails_group_uuid** - holds :uuid-thumb-group, a UUID of a [file group](https://uploadcare.com/api-refs/rest-api/v0.7.0/#operation/groupsList) with thumbnails for an output video, based on the thumbs [operation](https://uploadcare.com/docs/transformations/video-encoding/#operation-thumbs) parameters.
690
- - **problems** - problems related to your processing job, if any.
691
-
692
- To convert multiple videos just add params as a hash for each video to the first argument of the `Uploadcare::VideoConverter#convert` method:
693
-
694
- ```ruby
695
- Uploadcare::VideoConverter.convert(
696
- [
697
- { video_one_params }, { video_two_params }, ...
698
- ],
699
- store: false
700
- )
491
+
492
+ ## Add-ons
493
+
494
+ ```ruby
495
+ execution = client.addons.aws_rekognition_detect_labels(uuid: file.uuid)
496
+ client.addons.aws_rekognition_detect_labels_status(request_id: execution.request_id)
497
+
498
+ scan = client.addons.uc_clamav_virus_scan(uuid: file.uuid)
499
+ client.addons.uc_clamav_virus_scan_status(request_id: scan.request_id)
500
+
501
+ background = client.addons.remove_bg(uuid: file.uuid)
502
+ client.addons.remove_bg_status(request_id: background.request_id)
701
503
  ```
702
504
 
505
+ These methods return `Uploadcare::AddonExecution` resources.
506
+
507
+ ## Conversions
703
508
 
704
- To check a status of a video processing job you can simply use appropriate method of `Uploadcare::VideoConverter`:
509
+ Document conversions:
705
510
 
706
511
  ```ruby
707
- token = 911933811
708
- Uploadcare::VideoConverter.status(token)
512
+ info = client.conversions.documents.info(uuid: file.uuid)
513
+ job = client.conversions.documents.convert(uuid: file.uuid, format: :pdf)
514
+ status = client.conversions.documents.status(token: job.fetch("result").first.fetch("token"))
709
515
  ```
710
- `token` here is a processing job token, obtained in a response of a convert video request.
516
+
517
+ Video conversions:
711
518
 
712
519
  ```ruby
713
- # Response
714
- {
715
- :status => "finished",
716
- :error => nil,
717
- :result => {
718
- :uuid => "dc99200d-9bd6-4b43-bfa9-aa7bfaefca40",
719
- :thumbnails_group_uuid => "0f181f24-7551-42e5-bebc-14b15d9d3838~2"
720
- }
721
- }
520
+ job = client.conversions.videos.convert(uuid: file.uuid, format: :webm, quality: :normal)
521
+ status = client.conversions.videos.status(token: job.result.first.fetch("token"))
722
522
  ```
723
523
 
724
- Params in the response:
725
- - **status** - processing job status, can have one of the following values:
726
- - *pending* — video file is being prepared for conversion.
727
- - *processing* — video file processing is in progress.
728
- - *finished* — the processing is finished.
729
- - *failed* — we failed to process the video, see error for details.
730
- - *canceled* — video processing was canceled.
731
- - **error** - holds a processing error if we failed to handle your video.
732
- - **result** - repeats the contents of your processing output.
733
- - **thumbnails_group_uuid** - holds :uuid-thumb-group, a UUID of a file group with thumbnails for an output video, based on the thumbs operation parameters.
734
- - **uuid** - a UUID of your processed video file.
524
+ Document conversion `convert` returns the API response hash.
735
525
 
736
- More examples and options can be found [here](https://uploadcare.com/docs/transformations/video-encoding/#video-encoding).
526
+ Video conversion `convert` returns a `Uploadcare::VideoConversion` resource.
737
527
 
738
- ##### Document
528
+ ## Secure Delivery
739
529
 
740
- After each document file upload you obtain a file identifier in UUID format.
530
+ The gem includes signed URL generators for delivery workflows.
741
531
 
742
- You can use file identifier to determine the document format and possible conversion formats.
743
532
  ```ruby
744
- Uploadcare::DocumentConverter.info("dc99200d-9bd6-4b43-bfa9-aa7bfaefca40")
533
+ generator = Uploadcare::SignedUrlGenerators::AkamaiGenerator.new(
534
+ cdn_host: "example.com",
535
+ secret_key: "your_hex_encoded_akamai_secret"
536
+ )
745
537
 
746
- # Response
747
- {:error=>nil, :format=>{
748
- :name=>"jpg",
749
- :conversion_formats=>[
750
- {:name=>"avif"}, {:name=>"bmp"}, {:name=>"gif"}, {:name=>"ico"}, {:name=>"pcx"}, {:name=>"pdf"}, {:name=>"png"}, {:name=>"ps"}, {:name=>"svg"}, {:name=>"tga"}, {:name=>"thumbnail"}, {:name=>"tiff"}, {:name=>"wbmp"}, {:name=>"webp"}
751
- ]
752
- }}
538
+ signed_url = generator.generate_url("a7d5645e-5cd7-4046-819f-a6a2933bafe3")
753
539
  ```
754
540
 
755
- Then you can use this file identifier to convert your document to a new format:
541
+ Custom ACL and wildcard examples:
756
542
 
757
543
  ```ruby
758
- Uploadcare::DocumentConverter.convert(
759
- [
760
- {
761
- uuid: "dc99200d-9bd6-4b43-bfa9-aa7bfaefca40",
762
- format: "pdf"
763
- }
764
- ],
765
- store: false
766
- )
767
- ```
768
- or create an image of a particular page (if using image format):
769
- ```ruby
770
- Uploadcare::DocumentConverter.convert(
771
- [
772
- {
773
- uuid: "a4b9db2f-1591-4f4c-8f68-94018924525d",
774
- format: "png",
775
- page: 1
776
- }
777
- ],
778
- store: false
779
- )
544
+ generator.generate_url("a7d5645e-5cd7-4046-819f-a6a2933bafe3", "/*")
545
+ generator.generate_url("a7d5645e-5cd7-4046-819f-a6a2933bafe3", wildcard: true)
780
546
  ```
781
547
 
782
- This method accepts options to set properties of an output file:
548
+ ## Errors and Results
549
+
550
+ The convenience layer raises exceptions:
551
+
552
+ - `Uploadcare::Exception::RequestError`
553
+ - `Uploadcare::Exception::InvalidRequestError`
554
+ - `Uploadcare::Exception::NotFoundError`
555
+ - `Uploadcare::Exception::UploadError`
556
+ - `Uploadcare::Exception::MultipartUploadError`
557
+ - `Uploadcare::Exception::UploadTimeoutError`
558
+ - `Uploadcare::Exception::ThrottleError`
783
559
 
784
- - **uuid** — the file UUID-identifier.
785
- - **format** - defines the target format you want a source file converted to. The supported values are: `pdf` (default), `doc`, `docx`, `xls`, `xlsx`, `odt`, `ods`, `rtf`, `txt`, `jpg`, `png`. In case the format operation was not found, your input document will be converted to `pdf`.
786
- - **page** - a page number of a multi-paged document to either `jpg` or `png`. The method will not work for any other target formats.
560
+ Example:
787
561
 
788
562
  ```ruby
789
- # Response
790
- {
791
- :result => [
792
- {
793
- :original_source=>"a4b9db2f-1591-4f4c-8f68-94018924525d/document/-/format/png/-/page/1/",
794
- :token=>21120220
795
- :uuid=>"88fe5ada-90f1-422a-a233-3a0f3a7cf23c"
796
- }
797
- ],
798
- :problems=>{}
799
- }
563
+ begin
564
+ client.files.find(uuid: "missing")
565
+ rescue Uploadcare::Exception::NotFoundError => e
566
+ warn e.message
567
+ end
800
568
  ```
801
- Params in the response:
802
- - **result** - info related to your transformed output(-s):
803
- - **original_source** - source file identifier including a target format, if present.
804
- - **token** - a processing job token that can be used to get a [job status](https://uploadcare.com/docs/transformations/document-conversion/#status) (see below).
805
- - **uuid** - UUID of your processed document file.
806
- - **problems** - problems related to your processing job, if any.
807
569
 
808
- To convert multiple documents just add params as a hash for each document to the first argument of the `Uploadcare::DocumentConverter#convert` method:
570
+ The raw API layer returns `Uploadcare::Result`:
809
571
 
810
572
  ```ruby
811
- Uploadcare::DocumentConverter.convert(
812
- [
813
- { doc_one_params }, { doc_two_params }, ...
814
- ],
815
- store: false
816
- )
573
+ result = client.api.rest.files.info(uuid: "file-uuid")
574
+
575
+ if result.success?
576
+ puts result.success
577
+ else
578
+ warn result.error_message
579
+ end
817
580
  ```
818
581
 
819
- To check a status of a document processing job you can simply use appropriate method of `Uploadcare::DocumentConverter`:
582
+ ## Request Options
583
+
584
+ Most API calls accept `request_options:` and pass them to the HTTP layer.
585
+
586
+ Example:
820
587
 
821
588
  ```ruby
822
- token = 21120220
823
- Uploadcare::DocumentConverter.status(token)
589
+ client.files.find(uuid: "file-uuid", request_options: { timeout: 10 })
824
590
  ```
825
- `token` here is a processing job token, obtained in a response of a convert document request.
591
+
592
+ Use this when you need per-request timeout control without changing the client’s default configuration.
593
+
594
+ ## Raw API Access
595
+
596
+ The gem exposes full endpoint-level access through `client.api`.
597
+
598
+ REST API:
599
+
600
+ ```ruby
601
+ client.api.rest.files.list(params: { limit: 10 })
602
+ client.api.rest.files.info(uuid: "file-uuid")
603
+ client.api.rest.project.show
604
+ client.api.rest.webhooks.list
605
+ ```
606
+
607
+ Upload API:
826
608
 
827
609
  ```ruby
828
- # Response
829
- {
830
- :status => "finished",
831
- :error => nil,
832
- :result => {
833
- :uuid => "a4b9db2f-1591-4f4c-8f68-94018924525d"
834
- }
835
- }
610
+ File.open("photo.jpg", "rb") do |io|
611
+ client.api.upload.files.direct(file: io, store: true)
612
+ end
613
+
614
+ client.api.upload.files.from_url(source_url: "https://example.com/image.jpg", async: true)
615
+ client.api.upload.groups.create(files: ["uuid-1", "uuid-2"])
836
616
  ```
837
617
 
838
- Params in the response:
839
- - **status** - processing job status, can have one of the following values:
840
- - *pending* — document file is being prepared for conversion.
841
- - *processing* — document file processing is in progress.
842
- - *finished* — the processing is finished.
843
- - *failed* — we failed to process the document, see error for details.
844
- - *canceled* — document processing was canceled.
845
- - **error** - holds a processing error if we failed to handle your document.
846
- - **result** - repeats the contents of your processing output.
847
- - **uuid** - a UUID of your processed document file.
618
+ Use this layer when you want exact control over the documented endpoints or when you are wrapping the gem from another library.
848
619
 
849
- More examples and options can be found [here](https://uploadcare.com/docs/transformations/document-conversion/#document-conversion)
620
+ The raw layer is part of the public surface, but it is intentionally less promoted than `client.files`, `client.groups`, and the other convenience accessors.
850
621
 
851
- ## Secure delivery
622
+ ## Examples
852
623
 
853
- You can use custom domain and CDN provider to deliver files with authenticated URLs (see [original documentation](https://uploadcare.com/docs/security/secure_delivery/)).
624
+ - [api_examples/README.md](./api_examples/README.md): one canonical script per documented REST and Upload API endpoint
625
+ - [examples/README.md](./examples/README.md): workflow-oriented demos built on the public client API
854
626
 
855
- To generate authenticated URL from the library, you should choose `Uploadcare::SignedUrlGenerators::AkamaiGenerator` (or create your own generator implementation):
627
+ Run examples with project-managed Ruby:
856
628
 
857
- ```ruby
858
- generator = Uploadcare::SignedUrlGenerators::AkamaiGenerator.new(cdn_host: 'example.com', secret_key: 'secret_key')
859
- # Optional parameters: ttl: 300, algorithm: 'sha256'
860
- generator.generate_url(uuid, acl = optional)
629
+ ```bash
630
+ mise exec -- ruby api_examples/rest_api/get_project.rb
631
+ mise exec -- ruby examples/simple_upload.rb spec/fixtures/kitten.jpeg
632
+ ```
861
633
 
862
- generator.generate_url("a7d5645e-5cd7-4046-819f-a6a2933bafe3")
863
- # https://example.com/a7d5645e-5cd7-4046-819f-a6a2933bafe3/?token=exp=1649405263~acl=/a7d5645e-5cd7-4046-819f-a6a2933bafe3/~hmac=a989cae5342f17013677f5a0e6577fc5594cc4e238fb4c95eda36634eb47018b
634
+ ## Upgrading from v4.x
864
635
 
865
- # You can pass in ACL as a second parameter to generate_url. See https://uploadcare.com/docs/security/secure-delivery/#authenticated-urls for supported acl formats
866
- generator.generate_url("a7d5645e-5cd7-4046-819f-a6a2933bafe3", '/*/')
867
- # https://example.com/a7d5645e-5cd7-4046-819f-a6a2933bafe3/?token=exp=1649405263~acl=/*/~hmac=3ce1152c6af8864b36d4dc721f08ca3cf0b3a20278d7f849e82c6c930d48ccc1
636
+ See:
868
637
 
869
- # Optionally you can use wildcard: true to generate a wildcard acl token
870
- generator.generate_url("a7d5645e-5cd7-4046-819f-a6a2933bafe3", wildcard: true)
871
- # https://example.com/a7d5645e-5cd7-4046-819f-a6a2933bafe3/?token=exp=1714233449~acl=/a7d5645e-5cd7-4046-819f-a6a2933bafe3/*~hmac=a568ee2a85dd90a8a8a1ef35ea0cc0ef0acb84fe81990edd3a06eacf10a52b4e
872
-
873
- # You can also pass in a custom ttl and algorithm to AkamaiGenerator
874
- generator = Uploadcare::SignedUrlGenerators::AkamaiGenerator.new(cdn_host: 'example.com', secret_key: 'secret_key', ttl: 10)
875
- generator.generate_url("a7d5645e-5cd7-4046-819f-a6a2933bafe3")
876
- # This generates a URL that expires in 10 seconds
877
- # https://example.com/a7d5645e-5cd7-4046-819f-a6a2933bafe3/?token=exp=1714233277~acl=/a7d5645e-5cd7-4046-819f-a6a2933bafe3/~hmac=f25343104aeced3004d2cc4d49807d8d7c732300b54b154c319da5283a871a71
878
- ```
879
- ## Useful links
880
-
881
- * [Development](https://github.com/uploadcare/uploadcare-ruby/blob/main/DEVELOPMENT.md)
882
- * [Uploadcare documentation](https://uploadcare.com/docs/?utm_source=github&utm_medium=referral&utm_campaign=uploadcare-ruby)
883
- * [Upload API reference](https://uploadcare.com/api-refs/upload-api/?utm_source=github&utm_medium=referral&utm_campaign=uploadcare-ruby)
884
- * [REST API reference](https://uploadcare.com/api-refs/rest-api/?utm_source=github&utm_medium=referral&utm_campaign=uploadcare-ruby)
885
- * [Changelog](./CHANGELOG.md)
886
- * [Contributing guide](https://github.com/uploadcare/.github/blob/master/CONTRIBUTING.md)
887
- * [Security policy](https://github.com/uploadcare/uploadcare-ruby/security/policy)
888
- * [Support](https://github.com/uploadcare/.github/blob/master/SUPPORT.md)
638
+ - [MIGRATING_V5.md](./MIGRATING_V5.md)
639
+ - [api_examples/README.md](./api_examples/README.md)