cloudinary 1.11.1 → 1.18.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/.github/ISSUE_TEMPLATE/bug_report.md +42 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +21 -0
- data/.github/pull_request_template.md +24 -0
- data/.gitignore +6 -1
- data/.travis.yml +15 -5
- data/CHANGELOG.md +149 -0
- data/Rakefile +3 -45
- data/cloudinary.gemspec +20 -4
- data/lib/active_storage/blob_key.rb +20 -0
- data/lib/active_storage/service/cloudinary_service.rb +229 -0
- data/lib/cloudinary.rb +31 -22
- data/lib/cloudinary/api.rb +173 -5
- data/lib/cloudinary/auth_token.rb +6 -4
- data/lib/cloudinary/carrier_wave.rb +3 -1
- data/lib/cloudinary/carrier_wave/remote.rb +3 -2
- data/lib/cloudinary/carrier_wave/storage.rb +2 -1
- data/lib/cloudinary/cloudinary_controller.rb +2 -4
- data/lib/cloudinary/helper.rb +30 -3
- data/lib/cloudinary/railtie.rb +7 -3
- data/lib/cloudinary/uploader.rb +35 -6
- data/lib/cloudinary/utils.rb +112 -40
- data/lib/cloudinary/version.rb +1 -1
- data/lib/cloudinary/video_helper.rb +96 -22
- data/lib/tasks/cloudinary/fetch_assets.rake +48 -0
- data/lib/tasks/{cloudinary.rake → cloudinary/sync_static.rake} +0 -0
- data/tools/allocate_test_cloud.sh +9 -0
- data/tools/get_test_cloud.sh +9 -0
- data/tools/update_version +29 -11
- data/vendor/assets/javascripts/cloudinary/jquery.cloudinary.js +48 -14
- data/vendor/assets/javascripts/cloudinary/jquery.fileupload.js +24 -4
- data/vendor/assets/javascripts/cloudinary/jquery.ui.widget.js +741 -561
- data/vendor/assets/javascripts/cloudinary/load-image.all.min.js +1 -1
- metadata +62 -67
- data/spec/access_control_spec.rb +0 -102
- data/spec/api_spec.rb +0 -567
- data/spec/archive_spec.rb +0 -129
- data/spec/auth_token_spec.rb +0 -77
- data/spec/cache_spec.rb +0 -109
- data/spec/cloudinary_helper_spec.rb +0 -325
- data/spec/cloudinary_spec.rb +0 -32
- data/spec/data/sync_static/app/assets/javascripts/1.coffee +0 -1
- data/spec/data/sync_static/app/assets/javascripts/1.js +0 -1
- data/spec/data/sync_static/app/assets/stylesheets/1.css +0 -3
- data/spec/docx.docx +0 -0
- data/spec/favicon.ico +0 -0
- data/spec/image_spec.rb +0 -107
- data/spec/logo.png +0 -0
- data/spec/rake_spec.rb +0 -160
- data/spec/sample_asset_file.tsv +0 -4
- data/spec/search_spec.rb +0 -109
- data/spec/spec_helper.rb +0 -266
- data/spec/storage_spec.rb +0 -44
- data/spec/streaminig_profiles_api_spec.rb +0 -74
- data/spec/support/helpers/temp_file_helpers.rb +0 -22
- data/spec/support/shared_contexts/rake.rb +0 -19
- data/spec/uploader_spec.rb +0 -392
- data/spec/utils_methods_spec.rb +0 -54
- data/spec/utils_spec.rb +0 -970
- data/spec/video_tag_spec.rb +0 -253
- data/spec/video_url_spec.rb +0 -185
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9179fe1c8105281b33780687c2bed49db41a35fca2d33ff15bd7fd4635d119f
|
4
|
+
data.tar.gz: 7b3bd01f71f1012bc7f315f707450ebb65537064e004fad615d713f489c4316c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 347fc122e9a31aa241afa194c09cdc3c0d19e63c5a206cc7751f4939de7c273769d648c7fd33af2cc4e7505fba0a5be9d555f1c3db1e2b41d45cfb58082e1cc3
|
7
|
+
data.tar.gz: 4f04b59256afe8f23c27625d94d761e9802e2ccd91d3c3dc992eb263e3430a7a053467c203d416d379815e317924f042c9310ac0f2b4ca185630307268aa66ca
|
@@ -0,0 +1,42 @@
|
|
1
|
+
---
|
2
|
+
name: Bug report
|
3
|
+
about: Bug report for Cloudinary Ruby SDK
|
4
|
+
title: ''
|
5
|
+
labels: ''
|
6
|
+
assignees: const-cloudinary
|
7
|
+
|
8
|
+
---
|
9
|
+
|
10
|
+
## Bug report for Cloudinary Ruby SDK
|
11
|
+
Before proceeding, please update to latest version and test if the issue persists
|
12
|
+
|
13
|
+
## Describe the bug in a sentence or two.
|
14
|
+
…
|
15
|
+
|
16
|
+
## Issue Type (Can be multiple)
|
17
|
+
[ ] Build - Can’t install or import the SDK
|
18
|
+
[ ] Performance - Performance issues
|
19
|
+
[ ] Behaviour - Functions aren’t working as expected (Such as generate URL)
|
20
|
+
[ ] Documentation - Inconsistency between the docs and behaviour
|
21
|
+
[ ] Other (Specify)
|
22
|
+
|
23
|
+
## Steps to reproduce
|
24
|
+
… if applicable
|
25
|
+
|
26
|
+
## Error screenshots or Stack Trace (if applicable)
|
27
|
+
…
|
28
|
+
|
29
|
+
## Operating System
|
30
|
+
[ ] Linux
|
31
|
+
[ ] Windows
|
32
|
+
[ ] OSX
|
33
|
+
[ ] All
|
34
|
+
|
35
|
+
## Environment and Libraries (fill in the version numbers)
|
36
|
+
Cloudinary Ruby SDK version - 0.0.0
|
37
|
+
Ruby Version - 0.0.0
|
38
|
+
Rails Version - 0.0.0
|
39
|
+
Other Libraries (Carrierwave, ActiveStorage, etc) - 0.0.0
|
40
|
+
|
41
|
+
## Repository
|
42
|
+
If possible, please provide a link to a reproducible repository that showcases the problem
|
@@ -0,0 +1,21 @@
|
|
1
|
+
---
|
2
|
+
name: Feature request
|
3
|
+
about: Feature request for Cloudinary Ruby SDK
|
4
|
+
title: ''
|
5
|
+
labels: ''
|
6
|
+
assignees: const-cloudinary
|
7
|
+
|
8
|
+
---
|
9
|
+
|
10
|
+
## Feature request for Cloudinary Ruby SDK
|
11
|
+
…(If your feature is for other SDKs, please request them there)
|
12
|
+
|
13
|
+
|
14
|
+
## Explain your use case
|
15
|
+
… (A high level explanation of why you need this feature)
|
16
|
+
|
17
|
+
## Describe the problem you’re trying to solve
|
18
|
+
… (A more technical view of what you’d like to accomplish, and how this feature will help you achieve it)
|
19
|
+
|
20
|
+
## Do you have a proposed solution?
|
21
|
+
… (yes, no? Please elaborate if needed)
|
@@ -0,0 +1,24 @@
|
|
1
|
+
### Brief Summary of Changes
|
2
|
+
<!--
|
3
|
+
Provide some context as to what was changed, from an implementation standpoint.
|
4
|
+
-->
|
5
|
+
|
6
|
+
#### What does this PR address?
|
7
|
+
[ ] Gitub issue (Add reference - #XX)
|
8
|
+
[ ] Refactoring
|
9
|
+
[ ] New feature
|
10
|
+
[ ] Bug fix
|
11
|
+
[ ] Adds more tests
|
12
|
+
|
13
|
+
#### Are tests included?
|
14
|
+
[ ] Yes
|
15
|
+
[ ] No
|
16
|
+
|
17
|
+
#### Reviewer, Please Note:
|
18
|
+
<!--
|
19
|
+
List anything here that the reviewer should pay special attention to. This might
|
20
|
+
include, for example:
|
21
|
+
• Dependence on other PRs
|
22
|
+
• Reference to other Cloudinary SDKs
|
23
|
+
• Changes that seem arbitrary without further explanations
|
24
|
+
-->
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -1,9 +1,19 @@
|
|
1
1
|
language: ruby
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
matrix:
|
4
|
+
include:
|
5
|
+
- name: "Ruby 1.9"
|
6
|
+
dist: precise
|
7
|
+
rvm: 1.9.3
|
8
|
+
before_install:
|
9
|
+
- gem install bundler -v 1.17.3
|
10
|
+
- name: "Ruby 2.5.3"
|
11
|
+
dist: xenial
|
12
|
+
rvm: ruby-2.5.3
|
13
|
+
before_install:
|
14
|
+
- gem install bundler
|
5
15
|
|
6
|
-
|
7
|
-
|
8
|
-
-
|
16
|
+
before_script: >
|
17
|
+
export CLOUDINARY_URL=$(bash tools/get_test_cloud.sh);
|
18
|
+
echo cloud_name: "$(echo $CLOUDINARY_URL | cut -d'@' -f2)"
|
9
19
|
script: bundle exec rspec
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,153 @@
|
|
1
1
|
|
2
|
+
1.18.0 / 2020-09-27
|
3
|
+
===================
|
4
|
+
|
5
|
+
New functionality and features
|
6
|
+
------------------------------
|
7
|
+
* Add `download_folder` helper
|
8
|
+
* Add support for `sources` in `video` tag
|
9
|
+
* Add structured metadata to Admin and Upload API
|
10
|
+
|
11
|
+
Other Changes
|
12
|
+
-------------
|
13
|
+
* Fix download of a raw file in ActiveStorage
|
14
|
+
* Update embedded `jquery.cloudinary.js` to fix ES5 compatibility issue
|
15
|
+
|
16
|
+
1.17.1 / 2020-08-25
|
17
|
+
===================
|
18
|
+
|
19
|
+
* Fix options handling issue in SassC
|
20
|
+
|
21
|
+
1.17.0 / 2020-08-21
|
22
|
+
===================
|
23
|
+
|
24
|
+
New functionality and features
|
25
|
+
------------------------------
|
26
|
+
|
27
|
+
* Add support for `eval` upload parameter
|
28
|
+
* Add support for 32-char signature length
|
29
|
+
|
30
|
+
Other Changes
|
31
|
+
-------------
|
32
|
+
|
33
|
+
* Fix escaping of query string characters in CarrierWave integration
|
34
|
+
* Fix detection integration test
|
35
|
+
* Integrate with sub-account test service
|
36
|
+
* Add pull request template
|
37
|
+
|
38
|
+
1.16.1 / 2020-07-06
|
39
|
+
===================
|
40
|
+
|
41
|
+
* Detect data URLs with suffix in mime type
|
42
|
+
* Fix `Invalid regular expression` error in Safari
|
43
|
+
|
44
|
+
1.16.0 / 2020-06-29
|
45
|
+
===================
|
46
|
+
|
47
|
+
New functionality and features
|
48
|
+
------------------------------
|
49
|
+
|
50
|
+
* Add support for uploading `StringIO`
|
51
|
+
|
52
|
+
Other Changes
|
53
|
+
-------------
|
54
|
+
|
55
|
+
* Set default cache storage to `file` in `CarrierWave`
|
56
|
+
* Fix `normalize_expression` to ignore predefined variables
|
57
|
+
* Fix sample projects
|
58
|
+
|
59
|
+
1.15.0 / 2020-06-11
|
60
|
+
===================
|
61
|
+
|
62
|
+
New functionality and features
|
63
|
+
------------------------------
|
64
|
+
|
65
|
+
* Add support for `accessibility_analysis` parameter
|
66
|
+
|
67
|
+
Other Changes
|
68
|
+
-------------
|
69
|
+
* Fix `download` function in `Cloudinary::CarrierWave`
|
70
|
+
* Fix handling of empty value in `if` parameter
|
71
|
+
* Fix consumption of configuration from environment variables
|
72
|
+
|
73
|
+
1.14.0 / 2020-05-06
|
74
|
+
===================
|
75
|
+
|
76
|
+
New functionality and features
|
77
|
+
------------------------------
|
78
|
+
|
79
|
+
* Add support of global folder in ActiveStorage
|
80
|
+
* Add duration to conditions in video
|
81
|
+
|
82
|
+
Other Changes
|
83
|
+
-------------
|
84
|
+
|
85
|
+
* Fix `URI.unescape is obsolete` warning
|
86
|
+
* Fix lingering Rails 6 autoload warnings
|
87
|
+
* Fix Ruby 1.9 CI build
|
88
|
+
* Allow setting uploader timeout to `nil`
|
89
|
+
* Update link to CarrierWave integration
|
90
|
+
* Update issue templates
|
91
|
+
|
92
|
+
1.13.2 / 2020-01-19
|
93
|
+
===================
|
94
|
+
|
95
|
+
* Fix asset extension detection in active storage service `url` method
|
96
|
+
|
97
|
+
1.13.1 / 2019-11-24
|
98
|
+
===================
|
99
|
+
|
100
|
+
* Remove `test_files` from `gemspec`
|
101
|
+
* Remove redundant binary files from `active_storage` spec
|
102
|
+
* Fix `rspec` deprecation warnings in Rails 6
|
103
|
+
* Add test for uploading IO
|
104
|
+
|
105
|
+
1.13.0 / 2019-11-14
|
106
|
+
===================
|
107
|
+
|
108
|
+
New functionality and features
|
109
|
+
------------------------------
|
110
|
+
* Add `SassC` `cloudinary-url` function
|
111
|
+
|
112
|
+
Other Changes
|
113
|
+
-------------
|
114
|
+
|
115
|
+
* Fix ActiveStorage download not using `ssl` for `https`
|
116
|
+
* Fix resource type detection in ActiveStorage
|
117
|
+
* Fix `storage_type` instance method in `Cloudinary::CarrierWave` module
|
118
|
+
* Fix sample project, limit sqlite3 to a compatible version
|
119
|
+
|
120
|
+
1.12.0 / 2019-10-02
|
121
|
+
=============
|
122
|
+
|
123
|
+
New functionality and features
|
124
|
+
------------------------------
|
125
|
+
|
126
|
+
* Add Cloudinary service for ActiveStorage
|
127
|
+
* Add `create_folder` Admin API method
|
128
|
+
* Add `delete_folder` Admin API method
|
129
|
+
* Add `cinemagraph_analysis` to `upload`, `explicit` and `resource` API methods
|
130
|
+
* Add `font_antialiasing` and `font_hinting` text style parameters
|
131
|
+
* Add `derived_next_cursor` parameter to `resource` Admin API
|
132
|
+
* Add `next_cursor` and `max_results` for `root_folders` and `subfolders` Admin API functions
|
133
|
+
* Add `jpeg` to `IMAGE_FORMATS`
|
134
|
+
* Add `pow` transformation operator
|
135
|
+
* Add `force_version` to `cloudinary_url`
|
136
|
+
* Support per corner values for the `radius` transformation parameter
|
137
|
+
* Support using multiple resource types when generating archives
|
138
|
+
* Support Google Storage fetch URL
|
139
|
+
|
140
|
+
Other Changes
|
141
|
+
-------------
|
142
|
+
* Ensure `CLOUDINARY_URL` starts with `cloudinary://`
|
143
|
+
* Reduce memory usage in `Cloudinary::Utils.cloudinary_url`
|
144
|
+
* Encode URL in Admin API methods
|
145
|
+
* Fix base64 data validation
|
146
|
+
* Return `video` as the `resource_type` for audio files
|
147
|
+
* Add language and platform version for ruby/rails user agent
|
148
|
+
* Fix TravisCI configuration for ruby 1.9
|
149
|
+
|
150
|
+
|
2
151
|
1.11.1 / 2018-12-22
|
3
152
|
===================
|
4
153
|
|
data/Rakefile
CHANGED
@@ -1,55 +1,13 @@
|
|
1
1
|
require 'bundler'
|
2
2
|
require 'fileutils'
|
3
|
-
require 'tmpdir'
|
4
|
-
require 'rest_client'
|
5
|
-
require 'json'
|
6
|
-
require 'rubygems/package'
|
7
|
-
|
8
3
|
require 'rspec/core/rake_task'
|
4
|
+
|
9
5
|
RSpec::Core::RakeTask.new(:spec)
|
10
6
|
task :default => :spec
|
11
7
|
|
12
8
|
Bundler::GemHelper.install_tasks
|
13
9
|
|
14
|
-
|
15
|
-
|
16
|
-
task :fetch_assets do
|
17
|
-
index_files = %w[jquery.ui.widget.js jquery.iframe-transport.js jquery.fileupload.js jquery.cloudinary.js]
|
18
|
-
processing_files = %w[canvas-to-blob.min.js load-image.all.min.js jquery.fileupload-process.js jquery.fileupload-image.js jquery.fileupload-validate.js]
|
19
|
-
files = index_files + processing_files
|
20
|
-
|
21
|
-
release = JSON(RestClient.get("https://api.github.com/repos/cloudinary/cloudinary_js/releases/latest"))
|
22
|
-
|
23
|
-
FileUtils.rm_rf 'vendor/assets'
|
24
|
-
html_folder = 'vendor/assets/html'
|
25
|
-
FileUtils.mkdir_p html_folder
|
26
|
-
js_folder = 'vendor/assets/javascripts/cloudinary'
|
27
|
-
FileUtils.mkdir_p js_folder
|
28
|
-
|
29
|
-
puts "Fetching cloudinary_js version #{release["tag_name"]}\n\n"
|
30
|
-
sio = StringIO.new(RestClient.get(release["tarball_url"]).body)
|
31
|
-
file =Zlib::GzipReader.new(sio)
|
32
|
-
tar = Gem::Package::TarReader.new(file)
|
33
|
-
tar.each_entry do |entry|
|
34
|
-
name = File.basename(entry.full_name)
|
35
|
-
if files.include? name
|
36
|
-
js_full_name = File.join(js_folder, name)
|
37
|
-
puts "Adding #{js_full_name}"
|
38
|
-
File.write js_full_name, entry.read
|
39
|
-
elsif name == 'cloudinary_cors.html'
|
40
|
-
html_full_name = File.join(html_folder, name)
|
41
|
-
puts "Adding #{html_full_name}"
|
42
|
-
File.write html_full_name, entry.read
|
43
|
-
end
|
44
|
-
end
|
45
|
-
puts "Creating 'index.js' and 'processing.js' files"
|
46
|
-
File.open("vendor/assets/javascripts/cloudinary/index.js", "w") do |f|
|
47
|
-
index_files.each { |name| f.puts "//= require ./#{name}" }
|
48
|
-
end
|
49
|
-
File.open("vendor/assets/javascripts/cloudinary/processing.js", "w") do |f|
|
50
|
-
processing_files.each { |name| f.puts "//= require ./#{name}" }
|
51
|
-
end
|
52
|
-
end
|
10
|
+
path = File.expand_path(__dir__)
|
11
|
+
Dir.glob("#{path}/lib/tasks/**/*.rake").each { |f| import f }
|
53
12
|
|
54
|
-
end
|
55
13
|
task :build => "cloudinary:fetch_assets"
|
data/cloudinary.gemspec
CHANGED
@@ -15,8 +15,7 @@ Gem::Specification.new do |s|
|
|
15
15
|
|
16
16
|
s.rubyforge_project = "cloudinary"
|
17
17
|
|
18
|
-
s.files = (`git ls-files`.split("\n") - `git ls-files samples
|
19
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.files = (`git ls-files`.split("\n") - `git ls-files {test,spec,features,samples}/*`.split("\n")) + Dir.glob("vendor/assets/javascripts/*/*") + Dir.glob("vendor/assets/html/*")
|
20
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
21
20
|
s.require_paths = ["lib"]
|
22
21
|
|
@@ -25,9 +24,26 @@ Gem::Specification.new do |s|
|
|
25
24
|
|
26
25
|
s.add_development_dependency "actionpack"
|
27
26
|
s.add_development_dependency "nokogiri"
|
28
|
-
|
27
|
+
|
28
|
+
if RUBY_VERSION >= "2.2.0"
|
29
|
+
s.add_development_dependency "rake", ">= 13.0.1"
|
30
|
+
else
|
31
|
+
s.add_development_dependency "rake", "<= 12.2.1"
|
32
|
+
end
|
33
|
+
|
34
|
+
s.add_development_dependency "sqlite3"
|
29
35
|
s.add_development_dependency "rspec", '>=3.5'
|
36
|
+
s.add_development_dependency "rspec-retry"
|
37
|
+
s.add_development_dependency "rails", "~>5.2" if RUBY_VERSION >= "2.2.2"
|
38
|
+
|
39
|
+
s.add_development_dependency "railties", "<= 4.2.7" if RUBY_VERSION <= "1.9.3"
|
30
40
|
s.add_development_dependency "rspec-rails"
|
41
|
+
|
31
42
|
s.add_development_dependency "rubyzip", "<=1.2.0" # support testing Ruby 1.9
|
32
|
-
|
43
|
+
|
44
|
+
if RUBY_VERSION <= "2.4.0"
|
45
|
+
s.add_development_dependency "simplecov", "<= 0.17.1" # support testing Ruby 1.9
|
46
|
+
else
|
47
|
+
s.add_development_dependency "simplecov", "> 0.18.0"
|
48
|
+
end
|
33
49
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Allow Blob attributes to be passed down to the service
|
2
|
+
# attributes includes
|
3
|
+
# - key - the string the BlobKey represents
|
4
|
+
# - content_type
|
5
|
+
# - filename
|
6
|
+
module ActiveStorage
|
7
|
+
class BlobKey < String
|
8
|
+
attr_reader :attributes
|
9
|
+
def initialize(attributes)
|
10
|
+
if attributes.is_a? Hash
|
11
|
+
attributes.symbolize_keys!
|
12
|
+
super(attributes[:key])
|
13
|
+
@attributes = attributes
|
14
|
+
else
|
15
|
+
super(attributes)
|
16
|
+
@attributes = {key: attributes} if attributes
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,229 @@
|
|
1
|
+
require 'active_storage/blob_key'
|
2
|
+
require 'cloudinary/helper'
|
3
|
+
require 'net/http'
|
4
|
+
|
5
|
+
unless ActiveStorage::Blob.method_defined? :original_key
|
6
|
+
class ActiveStorage::Blob
|
7
|
+
alias_method :original_key, :key
|
8
|
+
|
9
|
+
def key
|
10
|
+
original_key
|
11
|
+
ActiveStorage::BlobKey.new(@attributes.as_json)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module CloudinaryHelper
|
17
|
+
alias cloudinary_url_internal_original cloudinary_url_internal
|
18
|
+
|
19
|
+
def cloudinary_url_internal(source, options = {})
|
20
|
+
source = ActiveStorage::Blob.service.public_id(source) if defined? ActiveStorage::Blob.service.public_id
|
21
|
+
cloudinary_url_internal_original(source, options)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module ActiveStorage
|
26
|
+
class Service::CloudinaryService < Service
|
27
|
+
module Headers
|
28
|
+
CONTENT_TYPE = "Content-Type".freeze
|
29
|
+
CONTENT_MD5 = "Content-MD5".freeze
|
30
|
+
end
|
31
|
+
attr_reader :upload_options
|
32
|
+
|
33
|
+
def initialize(**options)
|
34
|
+
@options = options
|
35
|
+
end
|
36
|
+
|
37
|
+
def upload(key, io, filename: nil, checksum: nil, **options)
|
38
|
+
instrument :upload, key: key, checksum: checksum do
|
39
|
+
begin
|
40
|
+
extra_headers = checksum.nil? ? {} : {Headers::CONTENT_MD5 => checksum}
|
41
|
+
options = @options.merge(options)
|
42
|
+
Cloudinary::Uploader.upload(
|
43
|
+
io,
|
44
|
+
public_id: public_id_internal(key),
|
45
|
+
resource_type: resource_type(io, key),
|
46
|
+
context: {active_storage_key: key, checksum: checksum},
|
47
|
+
extra_headers: extra_headers,
|
48
|
+
**options
|
49
|
+
)
|
50
|
+
rescue CloudinaryException => e
|
51
|
+
raise ActiveStorage::IntegrityError, e.message, e.backtrace
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def url(key, filename: nil, content_type: '', **options)
|
57
|
+
instrument :url, key: key do |payload|
|
58
|
+
url = Cloudinary::Utils.cloudinary_url(
|
59
|
+
public_id(key),
|
60
|
+
resource_type: resource_type(nil, key),
|
61
|
+
format: ext_for_file(key, filename, content_type),
|
62
|
+
**@options.merge(options.symbolize_keys)
|
63
|
+
)
|
64
|
+
|
65
|
+
payload[:url] = url
|
66
|
+
|
67
|
+
url
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def url_for_direct_upload(key, **options)
|
72
|
+
instrument :url, key: key do |payload|
|
73
|
+
options = {:resource_type => resource_type(nil, key)}.merge(@options.merge(options.symbolize_keys))
|
74
|
+
options[:public_id] = public_id_internal(key)
|
75
|
+
options[:context] = {active_storage_key: key}
|
76
|
+
options.delete(:file)
|
77
|
+
payload[:url] = api_uri("upload", options)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def headers_for_direct_upload(key, content_type:, checksum:, **)
|
82
|
+
{
|
83
|
+
Headers::CONTENT_TYPE => content_type,
|
84
|
+
Headers::CONTENT_MD5 => checksum,
|
85
|
+
}
|
86
|
+
end
|
87
|
+
|
88
|
+
def delete(key)
|
89
|
+
instrument :delete, key: key do
|
90
|
+
Cloudinary::Uploader.destroy public_id(key), resource_type: resource_type(nil, key)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def delete_prefixed(prefix)
|
95
|
+
# This method is used by ActiveStorage to delete derived resources after the main resource was deleted.
|
96
|
+
# In Cloudinary, the derived resources are deleted automatically when the main resource is deleted.
|
97
|
+
end
|
98
|
+
|
99
|
+
def exist?(key)
|
100
|
+
instrument :exist, key: key do |payload|
|
101
|
+
begin
|
102
|
+
Cloudinary::Api.resource public_id(key), resource_type: resource_type(nil, key)
|
103
|
+
true
|
104
|
+
rescue Cloudinary::Api::NotFound => e
|
105
|
+
false
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def download(key, &block)
|
111
|
+
uri = URI(url(key))
|
112
|
+
if block_given?
|
113
|
+
instrument :streaming_download, key: key do
|
114
|
+
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
115
|
+
request = Net::HTTP::Get.new uri
|
116
|
+
http.request request do |response|
|
117
|
+
response.read_body &block
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
else
|
122
|
+
instrument :download, key: key do
|
123
|
+
res = Net::HTTP::get_response(uri)
|
124
|
+
res.body
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Return the partial content in the byte +range+ of the file at the +key+.
|
130
|
+
def download_chunk(key, range)
|
131
|
+
url = Cloudinary::Utils.unsigned_download_url(public_id(key), resource_type: resource_type(nil, key))
|
132
|
+
uri = URI(url)
|
133
|
+
instrument :download, key: key do
|
134
|
+
req = Net::HTTP::Get.new(uri)
|
135
|
+
range_end = case
|
136
|
+
when range.end.nil? then ''
|
137
|
+
when range.exclude_end? then range.end - 1
|
138
|
+
else range.end
|
139
|
+
end
|
140
|
+
req['range'] = "bytes=#{[range.begin, range_end].join('-')}"
|
141
|
+
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
142
|
+
http.request(req)
|
143
|
+
end
|
144
|
+
res.body.force_encoding(Encoding::BINARY)
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
def public_id(key)
|
150
|
+
return key unless @options[:folder]
|
151
|
+
|
152
|
+
File.join(@options.fetch(:folder), public_id_internal(key))
|
153
|
+
end
|
154
|
+
|
155
|
+
private
|
156
|
+
|
157
|
+
def api_uri(action, options)
|
158
|
+
base_url = Cloudinary::Utils.cloudinary_api_url(action, options)
|
159
|
+
upload_params = Cloudinary::Uploader.build_upload_params(options)
|
160
|
+
|
161
|
+
upload_params.reject! { |k, v| Cloudinary::Utils.safe_blank?(v) }
|
162
|
+
unless options[:unsigned]
|
163
|
+
upload_params = Cloudinary::Utils.sign_request(upload_params, options)
|
164
|
+
end
|
165
|
+
"#{base_url}?#{upload_params.to_query}"
|
166
|
+
end
|
167
|
+
|
168
|
+
# Helper method for getting the filename extension.
|
169
|
+
#
|
170
|
+
# It does the best effort when original filename does not include extension, but we know the mime-type.
|
171
|
+
#
|
172
|
+
# @param [ActiveStorage::BlobKey] key The blob key with attributes.
|
173
|
+
# @param [ActiveStorage::Filename] filename The original filename.
|
174
|
+
# @param [string] content_type The content type of the file.
|
175
|
+
#
|
176
|
+
# @return [string] The extension of the filename.
|
177
|
+
def ext_for_file(key, filename, content_type)
|
178
|
+
if filename.blank?
|
179
|
+
options = key.respond_to?(:attributes) ? key.attributes : {}
|
180
|
+
filename = ActiveStorage::Filename.new(options[:filename]) if options.has_key?(:filename)
|
181
|
+
end
|
182
|
+
ext = filename.respond_to?(:extension_without_delimiter) ? filename.extension_without_delimiter : nil
|
183
|
+
|
184
|
+
return ext unless ext.blank?
|
185
|
+
|
186
|
+
# Raw files are not convertible, no extension guessing for them
|
187
|
+
return nil if content_type_to_resource_type(content_type).eql?('raw')
|
188
|
+
|
189
|
+
# Fallback when there is no extension.
|
190
|
+
@formats ||= Hash.new do |h, key|
|
191
|
+
ext = Rack::Mime::MIME_TYPES.invert[key]
|
192
|
+
h[key] = ext.slice(1..-1) unless ext.nil?
|
193
|
+
end
|
194
|
+
@formats[content_type]
|
195
|
+
end
|
196
|
+
|
197
|
+
def public_id_internal(key)
|
198
|
+
# TODO: Allow custom manipulation of key to obscure how we store in Cloudinary
|
199
|
+
key
|
200
|
+
end
|
201
|
+
|
202
|
+
def content_type_to_resource_type(content_type)
|
203
|
+
type, subtype = content_type.split('/')
|
204
|
+
case type
|
205
|
+
when 'video', 'audio'
|
206
|
+
'video'
|
207
|
+
when 'text'
|
208
|
+
'raw'
|
209
|
+
when 'application'
|
210
|
+
case subtype
|
211
|
+
when 'pdf', 'postscript'
|
212
|
+
'image'
|
213
|
+
when 'vnd.apple.mpegurl', 'x-mpegurl', 'mpegurl' # m3u8
|
214
|
+
'video'
|
215
|
+
else
|
216
|
+
'raw'
|
217
|
+
end
|
218
|
+
else
|
219
|
+
'image'
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def resource_type(io, key = "")
|
224
|
+
options = key.respond_to?(:attributes) ? key.attributes : {}
|
225
|
+
content_type = options[:content_type] || (io.nil? ? '' : Marcel::MimeType.for(io))
|
226
|
+
content_type_to_resource_type(content_type)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|