mountable_file_server 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +17 -7
- data/lib/mountable_file_server/adapter.rb +10 -5
- data/lib/mountable_file_server/client.rb +44 -0
- data/lib/mountable_file_server/file_accessor.rb +4 -4
- data/lib/mountable_file_server/metadata.rb +45 -0
- data/lib/mountable_file_server/rails.rb +2 -0
- data/lib/mountable_file_server/server.rb +49 -0
- data/lib/mountable_file_server/storage.rb +3 -3
- data/lib/mountable_file_server/uri.rb +0 -15
- data/lib/mountable_file_server/version.rb +1 -1
- data/lib/mountable_file_server.rb +5 -19
- data/mountable_file_server.gemspec +5 -6
- data/vendor/assets/javascripts/mountable_file_server.js +37 -54
- metadata +22 -35
- data/lib/mountable_file_server/configuration.rb +0 -10
- data/lib/mountable_file_server/endpoint.rb +0 -58
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9eca97072a7e354d3523e099982afc7cf4234516
|
4
|
+
data.tar.gz: 938444d589b364fb81bb16ab26244425601ba4eb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 09226be2ad7e5f2ccfac19be367b42f44d94e9570a91a2046f541468a1aaca317eae56baf4829455e450814c831e30f3147897ee344f842f245ca846a812d45b
|
7
|
+
data.tar.gz: 9f5d940813c63c26497be28472b5e12175ca4be1bec7903f8f5f21fe6412f89cdddaf26e75be3e2e3b4de40a628f898030e33b8f2b509c312625781edcd8067c
|
data/README.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
Mountable File Server can be used with any Ruby (on Rails) application and it removes the pain associated with file uploads.
|
2
|
+
|
3
|
+
## Core Idea
|
4
|
+
app only stores reference to uploaded file
|
5
|
+
|
6
|
+
## MountableFileServer::Server
|
7
|
+
The core of Mountable File Server (MFS) is a small HTTP API that accepts file uploads and offers endpoints to interact with uploaded files. While the frontend deals directly with the HTTP API, your Ruby application will want to use the Ruby Client `MountableFileServer::Client`.
|
8
|
+
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
|
1
14
|
MountableFileServer was born out of my frustations with existing Ruby based file upload solutions. It is certainly not comparable with existing feature-rich plug-and-play solutions that are tied to Ruby on Rails.
|
2
15
|
|
3
16
|
The fundamental idea is that your application should not be tied to files or handling the upload process. Instead this is handled by a dedicated server which can be run as independet process or be mounted inside your application. It accepts file uploads and returns an unique identifier for the file. This unique identifier is basically a string and the only thing your application has to remember in order to work with uploaded files.
|
@@ -98,11 +111,8 @@ Returns the URL for an uploaded file. Only works for public files, if you pass t
|
|
98
111
|
`MountableFileServer::Adapter#pathname_for(id)`
|
99
112
|
Returns a [Pathname](http://ruby-doc.org/stdlib-2.2.2/libdoc/pathname/rdoc/Pathname.html) object for the uploaded file. The pathname will always point to the file on disk independent from the files type or current storage location.
|
100
113
|
|
101
|
-
|
102
|
-
TBW
|
103
|
-
|
104
|
-
## Deployment
|
105
|
-
TBW
|
114
|
+
# Publish on RubyGems.org
|
106
115
|
|
107
|
-
|
108
|
-
|
116
|
+
1. Increment `lib/mountable_image_server/version.rb` to your liking.
|
117
|
+
2. Make a Git commit.
|
118
|
+
3. Run `bundle exec rake release`.
|
@@ -1,8 +1,12 @@
|
|
1
|
+
require 'mountable_file_server/storage'
|
2
|
+
require 'mountable_file_server/unique_identifier'
|
3
|
+
require 'mountable_file_server/file_accessor'
|
4
|
+
|
1
5
|
module MountableFileServer
|
2
6
|
class Adapter
|
3
7
|
attr_reader :configuration
|
4
8
|
|
5
|
-
def initialize(configuration = MountableFileServer.
|
9
|
+
def initialize(configuration = MountableFileServer.config)
|
6
10
|
@configuration = configuration
|
7
11
|
end
|
8
12
|
|
@@ -23,14 +27,15 @@ module MountableFileServer
|
|
23
27
|
Storage.new(configuration).move_to_permanent_storage uid
|
24
28
|
end
|
25
29
|
|
26
|
-
def
|
30
|
+
def remove_from_storage(uid)
|
27
31
|
uid = UniqueIdentifier.new uid
|
28
|
-
Storage.new(configuration).
|
32
|
+
Storage.new(configuration).remove_from_storage uid
|
29
33
|
end
|
30
34
|
|
31
35
|
def url_for(uid)
|
32
|
-
uid = UniqueIdentifier.new uid
|
33
|
-
FileAccessor.new(uid, configuration).url
|
36
|
+
# uid = UniqueIdentifier.new uid
|
37
|
+
# FileAccessor.new(uid, configuration).url
|
38
|
+
configuration.base_url + uid
|
34
39
|
end
|
35
40
|
|
36
41
|
def pathname_for(uid)
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
module MountableFileServer
|
6
|
+
class Client
|
7
|
+
def move_to_permanent_storage(fid)
|
8
|
+
if MountableFileServer.config.base_url.start_with?('http')
|
9
|
+
uri = ::URI.parse(MountableFileServer.config.base_url)
|
10
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
11
|
+
http.set_debug_output($stdout)
|
12
|
+
request = Net::HTTP::Post.new(uri.request_uri + fid + '/store-permanent')
|
13
|
+
|
14
|
+
http.request(request)
|
15
|
+
else
|
16
|
+
MountableFileServer::Server.new.call({
|
17
|
+
"rack.input" => StringIO.new(""),
|
18
|
+
"REQUEST_METHOD"=> "POST",
|
19
|
+
"PATH_INFO"=> "/#{fid}/store-permanent",
|
20
|
+
})
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def remove_from_storage(fid)
|
25
|
+
if MountableFileServer.config.base_url.start_with?('http')
|
26
|
+
uri = ::URI.parse(MountableFileServer.config.base_url)
|
27
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
28
|
+
request = Net::HTTP::Delete.new(uri.request_uri + fid)
|
29
|
+
|
30
|
+
http.request(request)
|
31
|
+
else
|
32
|
+
MountableFileServer::Server.new.call({
|
33
|
+
"rack.input" => StringIO.new(""),
|
34
|
+
"REQUEST_METHOD"=> "DELETE",
|
35
|
+
"PATH_INFO"=> "/#{fid}",
|
36
|
+
})
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def url_for(fid)
|
41
|
+
MountableFileServer.config.base_url + fid
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -7,17 +7,17 @@ module MountableFileServer
|
|
7
7
|
class FileAccessor
|
8
8
|
attr_reader :uid, :configuration
|
9
9
|
|
10
|
-
def initialize(uid, configuration = MountableFileServer.
|
10
|
+
def initialize(uid, configuration = MountableFileServer.config)
|
11
11
|
@uid = uid
|
12
12
|
@configuration = configuration
|
13
13
|
end
|
14
14
|
|
15
15
|
def temporary_pathname
|
16
|
-
Pathname(configuration.
|
16
|
+
Pathname(configuration.storage_path) + 'tmp' + uid
|
17
17
|
end
|
18
18
|
|
19
19
|
def permanent_pathname
|
20
|
-
Pathname(configuration.
|
20
|
+
Pathname(configuration.storage_path) + uid.type + uid
|
21
21
|
end
|
22
22
|
|
23
23
|
def pathname
|
@@ -31,7 +31,7 @@ module MountableFileServer
|
|
31
31
|
def url
|
32
32
|
raise NotAccessibleViaURL unless uid.public?
|
33
33
|
|
34
|
-
URI.new (Pathname(configuration.
|
34
|
+
URI.new (Pathname(configuration.base_url) + uid).to_s
|
35
35
|
end
|
36
36
|
|
37
37
|
private
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'dimensions'
|
2
|
+
|
3
|
+
module MountableFileServer
|
4
|
+
class Metadata
|
5
|
+
attr_reader :size, :content_type, :height, :width
|
6
|
+
|
7
|
+
def initialize(size:, content_type:, width: nil, height: nil)
|
8
|
+
@size = size
|
9
|
+
@content_type = content_type
|
10
|
+
@width = width
|
11
|
+
@height = height
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_h
|
15
|
+
hash = {
|
16
|
+
size: size,
|
17
|
+
content_type: content_type
|
18
|
+
}
|
19
|
+
|
20
|
+
if width && height
|
21
|
+
hash = hash.merge({
|
22
|
+
height: height,
|
23
|
+
width: width
|
24
|
+
})
|
25
|
+
end
|
26
|
+
|
27
|
+
hash
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.for_path(path)
|
31
|
+
parameters = {}
|
32
|
+
|
33
|
+
parameters[:content_type] = `file --brief --mime-type #{path}`.strip
|
34
|
+
parameters[:size] = File.size(path)
|
35
|
+
|
36
|
+
if ['image/png', 'image/jpeg', 'image/gif', 'image/tiff'].include?(parameters[:content_type])
|
37
|
+
dimensions = Dimensions.dimensions(path)
|
38
|
+
parameters[:width] = dimensions[0]
|
39
|
+
parameters[:height] = dimensions[1]
|
40
|
+
end
|
41
|
+
|
42
|
+
new(parameters)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
require 'mountable_file_server/adapter'
|
5
|
+
require 'mountable_file_server/metadata'
|
6
|
+
|
7
|
+
module MountableFileServer
|
8
|
+
class Server < Sinatra::Base
|
9
|
+
post '/' do
|
10
|
+
adapter = Adapter.new
|
11
|
+
pathname = Pathname(params[:file][:tempfile].path)
|
12
|
+
type = params[:type]
|
13
|
+
fid = adapter.store_temporary(pathname, type, pathname.extname)
|
14
|
+
url = adapter.url_for(fid)
|
15
|
+
metadata = Metadata.for_path(pathname)
|
16
|
+
|
17
|
+
content_type :json
|
18
|
+
status 201
|
19
|
+
|
20
|
+
{
|
21
|
+
fid: fid,
|
22
|
+
url: url,
|
23
|
+
metadata: metadata.to_h
|
24
|
+
}.to_json
|
25
|
+
end
|
26
|
+
|
27
|
+
get '/:fid' do |fid|
|
28
|
+
adapter = Adapter.new
|
29
|
+
pathname = adapter.pathname_for(fid)
|
30
|
+
send_file pathname
|
31
|
+
end
|
32
|
+
|
33
|
+
post '/:fid/store-permanent' do |fid|
|
34
|
+
adapter = Adapter.new
|
35
|
+
adapter.move_to_permanent_storage(fid)
|
36
|
+
|
37
|
+
content_type :json
|
38
|
+
status 200
|
39
|
+
end
|
40
|
+
|
41
|
+
delete '/:fid' do |fid|
|
42
|
+
adapter = Adapter.new
|
43
|
+
adapter.remove_from_storage(fid)
|
44
|
+
|
45
|
+
content_type :json
|
46
|
+
status 200
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -2,7 +2,7 @@ module MountableFileServer
|
|
2
2
|
class Storage
|
3
3
|
attr_reader :configuration
|
4
4
|
|
5
|
-
def initialize(configuration = MountableFileServer.
|
5
|
+
def initialize(configuration = MountableFileServer.config)
|
6
6
|
@configuration = configuration
|
7
7
|
end
|
8
8
|
|
@@ -26,8 +26,8 @@ module MountableFileServer
|
|
26
26
|
source.rename destination
|
27
27
|
end
|
28
28
|
|
29
|
-
def
|
30
|
-
source = FileAccessor.new(uid, configuration).
|
29
|
+
def remove_from_storage(uid)
|
30
|
+
source = FileAccessor.new(uid, configuration).pathname
|
31
31
|
source.delete
|
32
32
|
end
|
33
33
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'uri'
|
2
2
|
require 'pathname'
|
3
|
-
require 'url_safe_base64'
|
4
3
|
|
5
4
|
module MountableFileServer
|
6
5
|
class URI < String
|
@@ -12,22 +11,8 @@ module MountableFileServer
|
|
12
11
|
UniqueIdentifier.new filename
|
13
12
|
end
|
14
13
|
|
15
|
-
def encoded_processing_instructions
|
16
|
-
/\.(\w+)\./.match(filename).captures.first
|
17
|
-
end
|
18
|
-
|
19
|
-
def decoded_processing_instructions
|
20
|
-
UrlSafeBase64.decode64 encoded_processing_instructions
|
21
|
-
end
|
22
|
-
|
23
14
|
def filename
|
24
15
|
Pathname(::URI.parse(self).path).basename.to_s
|
25
16
|
end
|
26
|
-
|
27
|
-
def resize(instructions)
|
28
|
-
encoded_instructions = UrlSafeBase64.encode64 instructions
|
29
|
-
|
30
|
-
URI.new self.gsub('.', ".#{encoded_instructions}.")
|
31
|
-
end
|
32
17
|
end
|
33
18
|
end
|
@@ -1,24 +1,10 @@
|
|
1
|
+
require "dry-configurable"
|
2
|
+
|
1
3
|
require "mountable_file_server/version"
|
2
4
|
|
3
5
|
module MountableFileServer
|
4
|
-
|
5
|
-
require "mountable_file_server/file_accessor"
|
6
|
-
require "mountable_file_server/unique_identifier"
|
7
|
-
require "mountable_file_server/storage"
|
8
|
-
require "mountable_file_server/uri"
|
9
|
-
|
10
|
-
require "mountable_file_server/adapter"
|
11
|
-
require "mountable_file_server/endpoint"
|
12
|
-
|
13
|
-
class << self
|
14
|
-
attr_writer :configuration
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.configuration
|
18
|
-
@configuration ||= Configuration.new
|
19
|
-
end
|
6
|
+
extend Dry::Configurable
|
20
7
|
|
21
|
-
|
22
|
-
|
23
|
-
end
|
8
|
+
setting :base_url
|
9
|
+
setting :storage_path
|
24
10
|
end
|
@@ -21,15 +21,14 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.7"
|
22
22
|
spec.add_development_dependency "rake", "~> 10.0"
|
23
23
|
spec.add_development_dependency "minitest", "~> 5.8.0"
|
24
|
-
spec.add_development_dependency "rails", "~>
|
24
|
+
spec.add_development_dependency "rails", "~> 5.0.2"
|
25
25
|
spec.add_development_dependency "capybara", "~> 2.4.4"
|
26
26
|
spec.add_development_dependency "sqlite3", "~> 1.3.10"
|
27
27
|
spec.add_development_dependency "poltergeist", "~> 1.6.0"
|
28
28
|
spec.add_development_dependency "rack-test", "~> 0.6.3"
|
29
|
-
spec.add_development_dependency "
|
29
|
+
spec.add_development_dependency "webmock", "~> 2.1.0"
|
30
30
|
|
31
|
-
spec.add_runtime_dependency "
|
32
|
-
spec.add_runtime_dependency "
|
33
|
-
spec.add_runtime_dependency "
|
34
|
-
spec.add_runtime_dependency "url_safe_base64"
|
31
|
+
spec.add_runtime_dependency "sinatra", "~> 2.0.0.rc1"
|
32
|
+
spec.add_runtime_dependency "dry-configurable", "~> 0.1.6"
|
33
|
+
spec.add_runtime_dependency "dimensions", "~> 1.3.0"
|
35
34
|
end
|
@@ -1,61 +1,44 @@
|
|
1
1
|
(function() {
|
2
|
-
var
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
}
|
35
|
-
}
|
36
|
-
|
37
|
-
xhr.upload.addEventListener('progress', function(progressEvent) {
|
38
|
-
if (progressEvent.lengthComputable) {
|
39
|
-
dispatchEvent($element, 'upload:progress', {
|
40
|
-
uploadId: uploadId,
|
41
|
-
progress: progressEvent
|
2
|
+
var MountableFileServerUploader = function(options) {
|
3
|
+
return {
|
4
|
+
url: options.url,
|
5
|
+
uploadFile: function(options) {
|
6
|
+
|
7
|
+
var file = options.file;
|
8
|
+
var type = options.type;
|
9
|
+
var onStart = options.onStart || function() {};
|
10
|
+
var onProgress = options.onProgress || function() {};
|
11
|
+
var onSuccess = options.onSuccess || function() {};
|
12
|
+
var xhr = new XMLHttpRequest();
|
13
|
+
var formData = new FormData();
|
14
|
+
|
15
|
+
formData.append('file', file);
|
16
|
+
formData.append('type', type);
|
17
|
+
|
18
|
+
xhr.open('POST', this.url, true);
|
19
|
+
|
20
|
+
xhr.onreadystatechange = function() {
|
21
|
+
if (xhr.readyState === 4 && xhr.status === 201) {
|
22
|
+
var response = JSON.parse(xhr.responseText);
|
23
|
+
|
24
|
+
response.original_filename = file.name;
|
25
|
+
|
26
|
+
onSuccess(response);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
xhr.upload.addEventListener('progress', function(progressEvent) {
|
31
|
+
if (progressEvent.lengthComputable) {
|
32
|
+
onProgress(progressEvent);
|
33
|
+
}
|
42
34
|
});
|
43
|
-
}
|
44
|
-
});
|
45
|
-
|
46
|
-
xhr.send(formData);
|
47
35
|
|
48
|
-
|
49
|
-
uploadId: uploadId,
|
50
|
-
file: file
|
51
|
-
});
|
52
|
-
};
|
36
|
+
xhr.send(formData);
|
53
37
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
}
|
38
|
+
onStart();
|
39
|
+
}
|
40
|
+
};
|
58
41
|
};
|
59
42
|
|
60
|
-
window.
|
43
|
+
window.MountableFileServerUploader = MountableFileServerUploader;
|
61
44
|
})();
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mountable_file_server
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Strauß
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-03-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: 5.0.2
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 5.0.2
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: capybara
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,75 +123,61 @@ dependencies:
|
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: 0.6.3
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
|
-
name:
|
126
|
+
name: webmock
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
129
|
- - "~>"
|
130
130
|
- !ruby/object:Gem::Version
|
131
|
-
version:
|
131
|
+
version: 2.1.0
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
136
|
- - "~>"
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version:
|
138
|
+
version: 2.1.0
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
|
-
name:
|
140
|
+
name: sinatra
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
143
|
- - "~>"
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version:
|
145
|
+
version: 2.0.0.rc1
|
146
146
|
type: :runtime
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
150
|
- - "~>"
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version:
|
152
|
+
version: 2.0.0.rc1
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
|
-
name:
|
154
|
+
name: dry-configurable
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
156
156
|
requirements:
|
157
157
|
- - "~>"
|
158
158
|
- !ruby/object:Gem::Version
|
159
|
-
version: 1.
|
159
|
+
version: 0.1.6
|
160
160
|
type: :runtime
|
161
161
|
prerelease: false
|
162
162
|
version_requirements: !ruby/object:Gem::Requirement
|
163
163
|
requirements:
|
164
164
|
- - "~>"
|
165
165
|
- !ruby/object:Gem::Version
|
166
|
-
version: 1.
|
167
|
-
- !ruby/object:Gem::Dependency
|
168
|
-
name: mini_magick
|
169
|
-
requirement: !ruby/object:Gem::Requirement
|
170
|
-
requirements:
|
171
|
-
- - ">="
|
172
|
-
- !ruby/object:Gem::Version
|
173
|
-
version: '0'
|
174
|
-
type: :runtime
|
175
|
-
prerelease: false
|
176
|
-
version_requirements: !ruby/object:Gem::Requirement
|
177
|
-
requirements:
|
178
|
-
- - ">="
|
179
|
-
- !ruby/object:Gem::Version
|
180
|
-
version: '0'
|
166
|
+
version: 0.1.6
|
181
167
|
- !ruby/object:Gem::Dependency
|
182
|
-
name:
|
168
|
+
name: dimensions
|
183
169
|
requirement: !ruby/object:Gem::Requirement
|
184
170
|
requirements:
|
185
|
-
- - "
|
171
|
+
- - "~>"
|
186
172
|
- !ruby/object:Gem::Version
|
187
|
-
version:
|
173
|
+
version: 1.3.0
|
188
174
|
type: :runtime
|
189
175
|
prerelease: false
|
190
176
|
version_requirements: !ruby/object:Gem::Requirement
|
191
177
|
requirements:
|
192
|
-
- - "
|
178
|
+
- - "~>"
|
193
179
|
- !ruby/object:Gem::Version
|
194
|
-
version:
|
180
|
+
version: 1.3.0
|
195
181
|
description: ''
|
196
182
|
email:
|
197
183
|
- david@strauss.io
|
@@ -208,10 +194,11 @@ files:
|
|
208
194
|
- Rakefile
|
209
195
|
- lib/mountable_file_server.rb
|
210
196
|
- lib/mountable_file_server/adapter.rb
|
211
|
-
- lib/mountable_file_server/
|
212
|
-
- lib/mountable_file_server/endpoint.rb
|
197
|
+
- lib/mountable_file_server/client.rb
|
213
198
|
- lib/mountable_file_server/file_accessor.rb
|
199
|
+
- lib/mountable_file_server/metadata.rb
|
214
200
|
- lib/mountable_file_server/rails.rb
|
201
|
+
- lib/mountable_file_server/server.rb
|
215
202
|
- lib/mountable_file_server/storage.rb
|
216
203
|
- lib/mountable_file_server/unique_identifier.rb
|
217
204
|
- lib/mountable_file_server/uri.rb
|
@@ -238,7 +225,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
238
225
|
version: '0'
|
239
226
|
requirements: []
|
240
227
|
rubyforge_project:
|
241
|
-
rubygems_version: 2.
|
228
|
+
rubygems_version: 2.5.1
|
242
229
|
signing_key:
|
243
230
|
specification_version: 4
|
244
231
|
summary: Simple mountable server that handles file uploads
|
@@ -1,58 +0,0 @@
|
|
1
|
-
require 'sinatra/base'
|
2
|
-
require 'url_safe_base64'
|
3
|
-
require 'mini_magick'
|
4
|
-
require 'pathname'
|
5
|
-
|
6
|
-
module MountableFileServer
|
7
|
-
class Endpoint < Sinatra::Base
|
8
|
-
attr_reader :configuration
|
9
|
-
|
10
|
-
def initialize(configuration = MountableFileServer.configuration)
|
11
|
-
@configuration = configuration
|
12
|
-
super
|
13
|
-
end
|
14
|
-
|
15
|
-
post '/' do
|
16
|
-
pathname = Pathname(params[:file][:tempfile].path)
|
17
|
-
type = params[:type]
|
18
|
-
adapter = Adapter.new configuration
|
19
|
-
uid = adapter.store_temporary(pathname, type, pathname.extname)
|
20
|
-
|
21
|
-
|
22
|
-
content_type :json
|
23
|
-
{ uid: uid }.to_json
|
24
|
-
end
|
25
|
-
|
26
|
-
get '/*' do
|
27
|
-
deliver_file unescape(request.path_info)
|
28
|
-
end
|
29
|
-
|
30
|
-
def deliver_file(filename)
|
31
|
-
path_to_file = File.join(configuration.stored_at, 'public', filename)
|
32
|
-
|
33
|
-
if File.file?(path_to_file)
|
34
|
-
send_file path_to_file
|
35
|
-
else
|
36
|
-
if filename.count('.') == 2
|
37
|
-
parts = filename.split('.')
|
38
|
-
base_filename = "#{parts[0]}.#{parts[2]}"
|
39
|
-
path_to_base_file = File.join(configuration.stored_at, 'public', base_filename)
|
40
|
-
|
41
|
-
if File.file?(path_to_base_file)
|
42
|
-
resize_command = UrlSafeBase64.decode64 parts[1]
|
43
|
-
image = MiniMagick::Image.open path_to_base_file
|
44
|
-
image.resize resize_command.to_s
|
45
|
-
image.write path_to_file
|
46
|
-
send_file path_to_file
|
47
|
-
else
|
48
|
-
not_found
|
49
|
-
end
|
50
|
-
else
|
51
|
-
not_found
|
52
|
-
end
|
53
|
-
|
54
|
-
not_found
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|