shrine-uploadcare 0.3.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 66200985dae4d285580e9820867b1433fd9212573bf840b7afe0937ffda15809
4
- data.tar.gz: cd080f6783e48d1daee215bd0b2cba70f9d9d3e9355fa9643907ab0745b74a12
3
+ metadata.gz: 826464c7fa00009924eb9b89da88c3fb66fcc9e1626b27c70a473f91ca4ca41e
4
+ data.tar.gz: 1ded6035d05ba1747284362a15e4f9066d327f40072b00168b472bb530293f16
5
5
  SHA512:
6
- metadata.gz: 72048ded05537ca65af704be57c10b99833d91a2d5296a345d91bc0db82f908d6cb4f80dacce571ee56e39e2e37fbf823842b393baf2451614dba2c80642ae62
7
- data.tar.gz: 2c9017d63e9f86ab45029fb7b64ecd22319803c379c66bb9d2de81e911290a9828a63d9b2faa08cf7082d5012a453faab5db750f9794abc1156bf3a2f17e8dda
6
+ metadata.gz: 9cfa46ced7eb2d3273dc008ca3c92989df3f6a08cd9db953d5e3a8fe489f0666a036183d3007afb58e1b3a3357747ec8f385b16afa3e9cb366815ae9ba4ebde7
7
+ data.tar.gz: 161ee61ee644f3d6bf5da0259f2206623fd19762d81d5c97c9552bf876acdee720bffb4fc6592bce10c6d6253a04410754164312b89acbd48739c701cbd3fd7c
data/README.md CHANGED
@@ -8,7 +8,7 @@ with an advanced HTML widget for direct uploads.
8
8
  ## Installation
9
9
 
10
10
  ```ruby
11
- gem "shrine-uploadcare"
11
+ gem "shrine-uploadcare", "~> 1.0"
12
12
  ```
13
13
 
14
14
  ## Usage
@@ -30,14 +30,11 @@ Shrine.storages = {
30
30
 
31
31
  ### Direct uploads
32
32
 
33
- Uploadcare supports uploading files directly to the service, freeing your
34
- application from accepting file uploads. The easiest way to do that is by using
35
- Uploadcare's [HTML widget], you can see how it can be used in the
36
- shrine-uploadcare [demo app].
33
+ The `Shrine::Storage::Uploadcare` class implements the `#presign` method, so it
34
+ should work with Shrine's [presign_endpoint] plugin and Uppy's [AwsS3] plugin.
37
35
 
38
- [Secure file uploads] are also supported, you can generate signatures with
39
- `#presign` on the storage, or using the [direct_upload plugin] with `presign:
40
- true`.
36
+ If that doesn't work, you can always use Shrine's [upload_endpoint] plugin with
37
+ Uppy's [XHRUpload] plugin.
41
38
 
42
39
  ### URL operations
43
40
 
@@ -48,49 +45,20 @@ photo.image_url(resize: "200x")
48
45
  photo.image_url(crop: ["200x300", :center])
49
46
  ```
50
47
 
51
- ### Upload options
48
+ ### Metadata
52
49
 
53
- You can add upload options using the upload_options plugin or using
54
- `:upload_options` on the storage:
50
+ Uploadcare metadata is automatically stored on upload:
55
51
 
56
- ```rb
57
- Shrine::Storage::Uploadcare.new(upload_options: {...}, **uploadcare_options)
58
- ```
59
-
60
- ### Storing information
61
-
62
- You can have all Uploadcare file information saved in the uploaded file's
63
- metadata:
64
-
65
- ```rb
66
- Shrine::Storage::Uploadcare.new(store_info: true, **uploadcare_options)
67
- ```
68
52
  ```rb
69
53
  user = User.create(avatar: image_file)
70
- user.avatar.metadata["uploadcare"] #=>
54
+ user.avatar.metadata
71
55
  # {
72
- # "type" => "file",
73
- # "result" => {
74
- # "original_file_url" => "http://www.ucarecdn.com/d1d2dc43-4904-4783-bb4d-fbcf64264e63/image.png",
75
- # "image_info" => {
76
- # "height" => 45,
77
- # "width" => 91,
78
- # "geo_location" => null,
79
- # "datetime_original" => null,
80
- # "format" => "PNG"
81
- # },
82
- # "mime_type" => "image/png",
83
- # "is_ready" => true,
84
- # "url" => "https://api.uploadcare.com/files/d1d2dc43-4904-4783-bb4d-fbcf64264e63/",
85
- # "uuid" => "d1d2dc43-4904-4783-bb4d-fbcf64264e63",
86
- # "original_filename" => "image.png",
87
- # "datetime_uploaded" => "2014-09-09T16:48:57.284Z",
88
- # "size" => 12952,
89
- # "is_image" => null,
90
- # "datetime_stored" => "2014-09-09T16:48:57.291Z",
91
- # "datetime_removed" => null,
92
- # "source" => "/03ccf9ab-f266-43fb-973d-a6529c55c2ae/"
93
- # }
56
+ # "height" => 45,
57
+ # "width" => 91,
58
+ # "geo_location" => null,
59
+ # "datetime_original" => null,
60
+ # "format" => "PNG",
61
+ # ...
94
62
  # }
95
63
  ```
96
64
 
@@ -126,8 +94,8 @@ $ rake test
126
94
 
127
95
  [Uploadcare]: https://uploadcare.com/
128
96
  [Shrine]: https://github.com/shrinerb/shrine
129
- [HTML widget]: https://uploadcare.com/documentation/widget/
130
- [demo app]: /demo
131
- [Secure file uploads]: https://uploadcare.com/documentation/upload/#secure-uploads
132
- [direct_upload plugin]: http://shrinerb.com/rdoc/classes/Shrine/Plugins/DirectUpload.html
133
97
  [URL operations]: https://uploadcare.com/documentation/cdn/
98
+ [presign_endpoint]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/presign_endpoint.md#readme
99
+ [upload_endpoint]: https://github.com/shrinerb/shrine/blob/master/doc/plugins/upload_endpoint.md#readme
100
+ [AwsS3]: https://uppy.io/docs/aws-s3/
101
+ [XHRUpload]: https://uppy.io/docs/xhr-upload/
@@ -9,159 +9,92 @@ class Shrine
9
9
  class Uploadcare
10
10
  Error = Class.new(StandardError)
11
11
 
12
- attr_reader :uploadcare
12
+ attr_reader :api
13
13
 
14
- def initialize(store_info: false, upload_options: {}, **options)
15
- @uploadcare = ::Uploadcare::Api.new(api_version: "0.5", **options)
16
- @store_info = store_info
17
- @upload_options = upload_options
14
+ def initialize(**options)
15
+ @api = ::Uploadcare::Api.new(**options)
18
16
  end
19
17
 
20
18
  def upload(io, id, shrine_metadata: {}, **upload_options)
21
- result = _upload(io, id, shrine_metadata: shrine_metadata, **upload_options)
22
- update_metadata!(shrine_metadata, result)
23
- update_id!(id, result)
19
+ file = _upload(io, id, shrine_metadata: shrine_metadata, **upload_options)
20
+ file.load_data
21
+
22
+ update_metadata!(shrine_metadata, file)
23
+ update_id!(id, file)
24
+
25
+ file
24
26
  end
25
27
 
26
28
  def open(id, **options)
27
29
  Down::Http.open(url(id), **options)
30
+ rescue Down::NotFound
31
+ raise Shrine::FileNotFound, "file #{id.inspect} not found on storage"
28
32
  end
29
33
 
30
34
  def exists?(id)
31
- response = api_client.get("/files/#{id}/")
32
- !!response.body["datetime_stored"]
35
+ file = api.file(id)
36
+ file.load_data
37
+ !!file.datetime_stored
33
38
  rescue ::Uploadcare::Error::RequestError::NotFound
34
39
  false
35
40
  end
36
41
 
37
42
  def delete(id)
38
- api_client.delete("/files/#{id}/storage/")
43
+ file = api.file(id)
44
+ file.delete
39
45
  end
40
46
 
41
47
  def url(id, **options)
42
- operations = options.to_a.map { |operation| operation.flatten.join("/") }
43
- file(id, operations).cdn_url(true)
44
- end
45
-
46
- def clear!
47
- response = api_client.get("/files/", stored: true, limit: 1000)
48
- loop do
49
- uuids = response.body["results"].map { |result| result.fetch("uuid") }
50
- batch_delete(uuids) unless uuids.empty?
51
- return if (next_url = response.body["next"]).nil?
52
- response = api_client.get(URI(next_url).request_uri)
53
- end
48
+ file = api.file(id)
49
+ file.operations = options.map { |operation| operation.flatten.join("/") }
50
+ file.cdn_url(true)
54
51
  end
55
52
 
56
53
  def presign(id = nil, **options)
57
54
  expire = Time.now.to_i + (options[:expires_in] || 60*60)
58
- secret_key = uploadcare.options[:private_key]
55
+ secret_key = api.options[:private_key]
59
56
 
60
57
  signature = Digest::MD5.hexdigest(secret_key + expire.to_s)
61
58
 
62
59
  fields = {
63
- UPLOADCARE_PUB_KEY: uploadcare.options[:public_key],
60
+ UPLOADCARE_PUB_KEY: api.options[:public_key],
64
61
  signature: signature,
65
62
  expire: expire,
66
63
  }
67
64
 
68
- url = upload_client.url_prefix + "base/"
65
+ url = URI.join(api.options[:upload_url_base], "base/").to_s
69
66
 
70
67
  { method: :post, url: url, fields: fields }
71
68
  end
72
69
 
73
- protected
74
-
75
- def file(id, operations = [])
76
- ::Uploadcare::Api::File.new(uploadcare, id, operations: operations)
70
+ def clear!
71
+ api.file_list(limit: 1000).each_slice(100) do |file_batch|
72
+ api.delete_files(file_batch)
73
+ end
77
74
  end
78
75
 
79
76
  private
80
77
 
81
- def _upload(io, id, **options)
82
- if uploadcare_file?(io)
83
- store(io, id, **options)
84
- else
85
- create(io, id, **options)
86
- end
87
- end
88
-
89
- def store(io, id, **options)
90
- response = api_client.put "/files/#{io.id}/storage/"
91
- response.body
92
- end
78
+ def _upload(io, id, shrine_metadata: {}, **upload_options)
79
+ options = { store: true }
80
+ options.merge!(upload_options)
93
81
 
94
- def create(io, id, **options)
95
82
  if remote_file?(io)
96
- create_from_url(io, id, **options)
83
+ api.upload_from_url(io.url, options)
97
84
  else
98
- create_from_file(io, id, **options)
99
- end
100
- end
101
-
102
- def create_from_url(io, id, shrine_metadata: {}, **upload_options)
103
- options = {source_url: io.url, store: 1, pub_key: uploadcare.options[:public_key]}
104
- options.update(@upload_options).update(upload_options)
105
- response = upload_client.post "/from_url/", options
106
- token = response.body.fetch("token")
107
-
108
- loop do
109
- response = upload_client.get "/from_url/status/", token: token
110
- raise Error, response.body["error"] if response.body["status"] == "error"
111
- break response.body if response.body["status"] == "success"
112
- sleep 0.5
113
- end
114
- rescue ::Uploadcare::Error::RequestError::Forbidden => error
115
- raise Error, "You must allow \"automatic file storing\" in project settings"
116
- end
117
-
118
- def create_from_file(io, id, shrine_metadata: {}, **upload_options)
119
- options = {UPLOADCARE_PUB_KEY: uploadcare.options[:public_key], UPLOADCARE_STORE: 1}
120
- options.update(@upload_options).update(upload_options)
121
- io = Faraday::UploadIO.new(io, shrine_metadata["mime_type"], shrine_metadata["filename"])
122
- io.instance_eval { def length; size; end } # hack for multipart-post
123
- response = upload_client.post "/base/", file: io, **options
124
- {"uuid" => response.body.fetch("file")}
125
- rescue ::Uploadcare::Error::RequestError::Forbidden => error
126
- raise Error, "You must allow \"automatic file storing\" in project settings"
127
- end
128
-
129
- def batch_delete(ids)
130
- ids.each_slice(100) do |ids_slice|
131
- api_client.delete("/files/storage/") do |request|
132
- request.body = ids_slice.to_json
133
- request.headers["Content-Type"] = "application/json"
85
+ Shrine.with_file(io) do |file|
86
+ api.upload(file, options)
134
87
  end
135
88
  end
136
89
  end
137
90
 
138
- def api_client
139
- uploadcare.instance_variable_get("@api_connection")
91
+ def update_metadata!(metadata, file)
92
+ metadata.merge!(file.image_info.to_h)
93
+ metadata.merge!("mime_type" => file.mime_type, "size" => file.size)
140
94
  end
141
95
 
142
- def upload_client
143
- uploadcare.instance_variable_get("@upload_connection")
144
- end
145
-
146
- def update_metadata!(metadata, result)
147
- retrieved_metadata = {
148
- "mime_type" => result["mime_type"],
149
- "width" => result["image_info"] && result["image_info"]["width"],
150
- "height" => result["image_info"] && result["image_info"]["height"],
151
- "size" => result["size"],
152
- }
153
- retrieved_metadata.reject! { |key, value| value.nil? }
154
- retrieved_metadata["uploadcare"] = result if @store_info
155
-
156
- metadata.update(retrieved_metadata)
157
- end
158
-
159
- def update_id!(id, result)
160
- id.replace(result.fetch("uuid"))
161
- end
162
-
163
- def uploadcare_file?(io)
164
- io.is_a?(UploadedFile) && io.storage.is_a?(Storage::Uploadcare)
96
+ def update_id!(id, file)
97
+ id.replace(file.uuid)
165
98
  end
166
99
 
167
100
  def remote_file?(io)
@@ -170,3 +103,15 @@ class Shrine
170
103
  end
171
104
  end
172
105
  end
106
+
107
+ module Uploadcare
108
+ module UploadingApi
109
+ class UploadParams
110
+ # fix determining MIME type
111
+ def extract_mime_type(file)
112
+ mime_type = MIME::Types.of(file.path).first
113
+ mime_type.content_type if mime_type
114
+ end
115
+ end
116
+ end
117
+ end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.name = "shrine-uploadcare"
3
- gem.version = "0.3.1"
3
+ gem.version = "1.0.0"
4
4
 
5
5
  gem.required_ruby_version = ">= 2.1"
6
6
 
@@ -13,9 +13,9 @@ Gem::Specification.new do |gem|
13
13
  gem.files = Dir["README.md", "LICENSE.txt", "lib/**/*.rb", "*.gemspec"]
14
14
  gem.require_path = "lib"
15
15
 
16
- gem.add_dependency "shrine", ">= 2.11", "< 4"
17
- gem.add_dependency "uploadcare-ruby", "~> 1.0.5"
18
- gem.add_dependency "down", "~> 4.4"
16
+ gem.add_dependency "shrine", ">= 3.0.0.rc", "< 4"
17
+ gem.add_dependency "uploadcare-ruby", "~> 2.1"
18
+ gem.add_dependency "down", "~> 5.0"
19
19
  gem.add_dependency "http", ">= 3.2", "< 5"
20
20
 
21
21
  gem.add_development_dependency "rake"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shrine-uploadcare
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Janko Marohnić
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-09-25 00:00:00.000000000 Z
11
+ date: 2019-09-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: shrine
@@ -16,7 +16,7 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '2.11'
19
+ version: 3.0.0.rc
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
22
  version: '4'
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: '2.11'
29
+ version: 3.0.0.rc
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '4'
@@ -36,28 +36,28 @@ dependencies:
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: 1.0.5
39
+ version: '2.1'
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: 1.0.5
46
+ version: '2.1'
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: down
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: '4.4'
53
+ version: '5.0'
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: '4.4'
60
+ version: '5.0'
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: http
63
63
  requirement: !ruby/object:Gem::Requirement