shrine-gridfs 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +9 -0
- data/lib/shrine/storage/gridfs.rb +79 -45
- data/shrine-gridfs.gemspec +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 32f189d0c100716ffe7658f1bf04e84f6ed05415
|
4
|
+
data.tar.gz: 2ede8fa5db17c83fff263cd33e7d1434cad9da96
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0cd1b8dfbfaaf44644777f45b087b49485dd19528c4a2b1eff61a0fb1e932b891f7e4be4150cc134deea9940045fb4784ed1ca08e13c3ebb437bf28b0378384
|
7
|
+
data.tar.gz: b8394324dea43b926e78ae961cfaecb949d98983c5afde5a0c0752c8074fd5b1ea3c70be7a6058c44f035cd3cef801af8a0e14aa003a750ab8af75bf17acbb20
|
data/README.md
CHANGED
@@ -40,6 +40,15 @@ change that via `:chunk_size`:
|
|
40
40
|
Shrine::Storage::Gridfs.new(client: client, chunk_size: 1*1024*1024) # 1MB
|
41
41
|
```
|
42
42
|
|
43
|
+
### Batch size
|
44
|
+
|
45
|
+
When Gridfs storage uploads or copies a file, it will ensure that no more
|
46
|
+
than `:batch_size` of data is loaded into memory at once (defaults to 5MB).
|
47
|
+
|
48
|
+
```rb
|
49
|
+
Shrine::Storage::Gridfs.new(client: client, batch_size: 10*1024*1024) # 10MB
|
50
|
+
```
|
51
|
+
|
43
52
|
### URLs
|
44
53
|
|
45
54
|
You can generate URLs through which the GridFS files will be streamed with the
|
@@ -8,53 +8,26 @@ class Shrine
|
|
8
8
|
class Gridfs
|
9
9
|
attr_reader :client, :prefix, :bucket, :chunk_size
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
def initialize(client:, prefix: "fs", chunk_size: 256*1024, **options)
|
11
|
+
def initialize(client:, prefix: "fs", chunk_size: 256*1024, batch_size: 5 * 1024*1024, **options)
|
14
12
|
@client = client
|
15
13
|
@prefix = prefix
|
16
14
|
@chunk_size = chunk_size
|
15
|
+
@batch_size = batch_size
|
17
16
|
@bucket = @client.database.fs(bucket_name: @prefix)
|
18
17
|
|
19
18
|
@bucket.send(:ensure_indexes!)
|
20
19
|
end
|
21
20
|
|
22
21
|
def upload(io, id, shrine_metadata: {}, **)
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
grid_chunks = Mongo::Grid::File::Chunk.split(chunk, file.info, offset ||= 0)
|
28
|
-
|
29
|
-
chunks_collection.insert_many(grid_chunks)
|
30
|
-
|
31
|
-
offset += grid_chunks.count
|
32
|
-
grid_chunks.each { |grid_chunk| grid_chunk.data.data.clear } # deallocate strings
|
33
|
-
chunk.clear # deallocate string
|
22
|
+
if copyable?(io, id)
|
23
|
+
copy(io, id, shrine_metadata: shrine_metadata)
|
24
|
+
else
|
25
|
+
create(io, id, shrine_metadata: shrine_metadata)
|
34
26
|
end
|
35
|
-
|
36
|
-
files_collection.find(_id: file.id).update_one(
|
37
|
-
"$set" => {
|
38
|
-
length: io.size,
|
39
|
-
uploadDate: Time.now.utc,
|
40
|
-
md5: file.info.md5.hexdigest,
|
41
|
-
}
|
42
|
-
)
|
43
|
-
end
|
44
|
-
|
45
|
-
def move(io, id, shrine_metadata: {}, **)
|
46
|
-
file = create_file(id, shrine_metadata: shrine_metadata)
|
47
|
-
|
48
|
-
chunks_collection.find(files_id: bson_id(io.id)).update_many("$set" => {files_id: file.id})
|
49
|
-
files_collection.delete_one(_id: bson_id(io.id))
|
50
|
-
end
|
51
|
-
|
52
|
-
def movable?(io, id)
|
53
|
-
io.is_a?(UploadedFile) && io.storage.is_a?(Storage::Gridfs)
|
54
27
|
end
|
55
28
|
|
56
29
|
def open(id)
|
57
|
-
content_length =
|
30
|
+
content_length = file_info(id)[:length]
|
58
31
|
stream = bucket.open_download_stream(bson_id(id))
|
59
32
|
|
60
33
|
Down::ChunkedIO.new(
|
@@ -65,7 +38,7 @@ class Shrine
|
|
65
38
|
end
|
66
39
|
|
67
40
|
def exists?(id)
|
68
|
-
!!
|
41
|
+
!!file_info(id)
|
69
42
|
end
|
70
43
|
|
71
44
|
def delete(id)
|
@@ -87,29 +60,90 @@ class Shrine
|
|
87
60
|
chunks_collection.find.delete_many
|
88
61
|
end
|
89
62
|
|
63
|
+
protected
|
64
|
+
|
65
|
+
def file_info(id)
|
66
|
+
bucket.find(_id: bson_id(id)).limit(1).first
|
67
|
+
end
|
68
|
+
|
69
|
+
def files_collection
|
70
|
+
bucket.files_collection
|
71
|
+
end
|
72
|
+
|
73
|
+
def chunks_collection
|
74
|
+
bucket.chunks_collection
|
75
|
+
end
|
76
|
+
|
90
77
|
private
|
91
78
|
|
79
|
+
def create(io, id, shrine_metadata: {})
|
80
|
+
file = create_file(id, shrine_metadata: shrine_metadata)
|
81
|
+
|
82
|
+
until io.eof?
|
83
|
+
chunk = io.read([@batch_size, chunk_size].max, buffer ||= "")
|
84
|
+
grid_chunks = Mongo::Grid::File::Chunk.split(chunk, file.info, offset ||= 0)
|
85
|
+
|
86
|
+
chunks_collection.insert_many(grid_chunks)
|
87
|
+
|
88
|
+
offset += grid_chunks.count
|
89
|
+
grid_chunks.each { |grid_chunk| grid_chunk.data.data.clear } # deallocate strings
|
90
|
+
chunk.clear # deallocate string
|
91
|
+
end
|
92
|
+
|
93
|
+
files_collection.find(_id: file.id).update_one("$set" => {
|
94
|
+
length: io.size,
|
95
|
+
uploadDate: Time.now.utc,
|
96
|
+
md5: file.info.md5.hexdigest,
|
97
|
+
})
|
98
|
+
end
|
99
|
+
|
100
|
+
def copy(io, id, shrine_metadata: {})
|
101
|
+
source_storage = io.storage
|
102
|
+
source_info = source_storage.file_info(io.id)
|
103
|
+
dest_info = source_info.merge(_id: BSON::ObjectId.new)
|
104
|
+
|
105
|
+
batch_size = (@batch_size.to_f / chunk_size).ceil
|
106
|
+
chunk_batches = source_storage.chunks_collection
|
107
|
+
.find(files_id: source_info[:_id])
|
108
|
+
.batch_size(batch_size).each_slice(batch_size)
|
109
|
+
|
110
|
+
chunk_batches.each do |chunks|
|
111
|
+
chunks.each do |chunk|
|
112
|
+
chunk[:_id] = BSON::ObjectId.new
|
113
|
+
chunk[:files_id] = dest_info[:_id]
|
114
|
+
end
|
115
|
+
|
116
|
+
chunks_collection.insert_many(chunks)
|
117
|
+
|
118
|
+
chunks.each do |chunk|
|
119
|
+
chunk[:data].data.clear # deallocate strings
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
dest_info[:uploadDate] = Time.now.utc
|
124
|
+
dest_info[:filename] = shrine_metadata["filename"] || id
|
125
|
+
files_collection.insert_one(dest_info)
|
126
|
+
id.replace(dest_info[:_id].to_s + File.extname(id))
|
127
|
+
end
|
128
|
+
|
129
|
+
def copyable?(io, id)
|
130
|
+
io.is_a?(UploadedFile) && io.storage.is_a?(Storage::Gridfs)
|
131
|
+
end
|
132
|
+
|
92
133
|
def create_file(id, shrine_metadata: {})
|
93
134
|
file = Mongo::Grid::File.new("",
|
94
135
|
filename: shrine_metadata["filename"] || id,
|
95
|
-
content_type: shrine_metadata["mime_type"],
|
136
|
+
content_type: shrine_metadata["mime_type"] || "application/octet-stream",
|
96
137
|
metadata: shrine_metadata,
|
97
138
|
chunk_size: chunk_size,
|
98
139
|
)
|
99
|
-
id.replace(file.id.to_s + File.extname(id))
|
100
140
|
|
101
141
|
bucket.insert_one(file)
|
102
142
|
|
143
|
+
id.replace(file.id.to_s + File.extname(id))
|
103
144
|
file.info.document[:md5] = Digest::MD5.new
|
104
|
-
file
|
105
|
-
end
|
106
|
-
|
107
|
-
def files_collection
|
108
|
-
bucket.files_collection
|
109
|
-
end
|
110
145
|
|
111
|
-
|
112
|
-
bucket.chunks_collection
|
146
|
+
file
|
113
147
|
end
|
114
148
|
|
115
149
|
def bson_id(id)
|
data/shrine-gridfs.gemspec
CHANGED