active_storage-send_zip 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.yml +11 -0
- data/Gemfile.lock +1 -1
- data/README.md +62 -21
- data/active_storage-send_zip.gemspec +1 -1
- data/lib/active_storage/send_zip.rb +6 -72
- data/lib/active_storage/send_zip/version.rb +2 -1
- data/lib/active_storage/send_zip_helper.rb +89 -0
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a5dbef1dda4a5236e3290d9cd38a23de7e296b5e404356bf222dfbeb0c75197b
|
4
|
+
data.tar.gz: d2558817de8b496c48606c1e3af71df086480eede14b55186ea4a5e7206bfe5c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 49f3758cc21c8a66dce8f69fe231c679f0802ad8374a222f8a178557ac668b5c2cf3ce7ea4a4f1d0c1e40dcb701a65c200de7bea3e82089cc56a3e20d9495e5f
|
7
|
+
data.tar.gz: 8830d24a60774f277e4576614243a077f661d08313259aaa501692ca5f58cb5bb13ef8975e6659432433d366195211e5f3c38c8bd25e2312feee1352908bf7a6
|
data/CHANGELOG.yml
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
0.2.0:
|
2
|
+
- move some methods to avoid to polute controller methods
|
3
|
+
- `ActiveStorage::SendZip#save_files_on_server` become `ActiveStorage::SendZipHelperSendZip#save_files_on_server`
|
4
|
+
- `SendZip#save_file_on_server` become `ActiveStorage::SendZipHelperSendZip#save_file_on_server`
|
5
|
+
- `SendZip#create_temporary_zip_file` become `ActiveStorage::SendZipHelperSendZip#create_temporary_zip_file`
|
6
|
+
- `send_zip` can now handle an `Hash` param to organize in subfolder
|
7
|
+
0.1.1:
|
8
|
+
- handle double filenames
|
9
|
+
- use a radom folder instead of fixed one (this was problematic qith multiples queries at the same times)
|
10
|
+
0.1.0:
|
11
|
+
- first versions
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,27 +1,14 @@
|
|
1
1
|
# ActiveStorage::SendZip
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/active_storage-send_zip.svg)](https://badge.fury.io/rb/active_storage-send_zip)
|
4
|
+
[![MIT Licence](https://badges.frapsoft.com/os/mit/mit.png?v=103)](https://opensource.org/licenses/mit-license.php)
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
## Installation
|
8
|
-
|
9
|
-
Add this line to your application's Gemfile:
|
10
|
-
|
11
|
-
```ruby
|
12
|
-
gem 'active_storage-send_zip'
|
13
|
-
```
|
14
|
-
|
15
|
-
And then execute:
|
16
|
-
|
17
|
-
$ bundle
|
18
|
-
|
19
|
-
Or install it yourself as:
|
20
|
-
|
21
|
-
$ gem install active_storage-send_zip
|
6
|
+
Add a `send_zip` method in your Rails controller to send a `.zip` file containing one or many [ActiveStorage](https://edgeguides.rubyonrails.org/active_storage_overview.html) objects.
|
22
7
|
|
23
8
|
## Usage
|
24
9
|
|
10
|
+
### With `Array`
|
11
|
+
|
25
12
|
Assuming you have an ActiveRecord model with ActiveStorage like this:
|
26
13
|
|
27
14
|
~~~ruby
|
@@ -51,6 +38,64 @@ class UsersController < ApplicationController
|
|
51
38
|
end
|
52
39
|
~~~
|
53
40
|
|
41
|
+
Will produce a `.zip` archive like this:
|
42
|
+
|
43
|
+
~~~
|
44
|
+
├── a.jpg
|
45
|
+
├── b.png
|
46
|
+
└── c.gif
|
47
|
+
~~~
|
48
|
+
|
49
|
+
Ii will also prevent duplicate filename and add an [`SecureRandom.uuid`](https://ruby-doc.org/stdlib-2.3.0/libdoc/securerandom/rdoc/SecureRandom.html) if two files as the same name.
|
50
|
+
|
51
|
+
|
52
|
+
### With `Hash`
|
53
|
+
|
54
|
+
You can also pass an `Hash` parameter at `send_zip` method to organize files in sublfolder:
|
55
|
+
|
56
|
+
~~~ruby
|
57
|
+
# app/controllers/holidays_controller.rb
|
58
|
+
class HolidaysController < ApplicationController
|
59
|
+
include ActiveStorage::SendZip
|
60
|
+
|
61
|
+
def zip
|
62
|
+
send_zip {
|
63
|
+
'Holidays in Lyon <3' => Holidays.where(place: 'lyon').first.pictures,
|
64
|
+
'Holidays in Paris' => Holidays.where(place: 'paris').first.pictures,
|
65
|
+
}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
~~~
|
69
|
+
|
70
|
+
Will produce a `.zip` archive like this:
|
71
|
+
|
72
|
+
~~~
|
73
|
+
├── Holidays in Lyon <3
|
74
|
+
│ ├── a.jpg
|
75
|
+
│ ├── b.png
|
76
|
+
│ └── c.gif
|
77
|
+
└── Holidays in Paris
|
78
|
+
├── a.jpg
|
79
|
+
├── b.png
|
80
|
+
└── c.gif
|
81
|
+
~~~
|
82
|
+
|
83
|
+
## Installation
|
84
|
+
|
85
|
+
Add this line to your application's Gemfile:
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
gem 'active_storage-send_zip'
|
89
|
+
```
|
90
|
+
|
91
|
+
And then execute:
|
92
|
+
|
93
|
+
$ bundle
|
94
|
+
|
95
|
+
Or install it yourself as:
|
96
|
+
|
97
|
+
$ gem install active_storage-send_zip
|
98
|
+
|
54
99
|
## Development
|
55
100
|
|
56
101
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -61,10 +106,6 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
61
106
|
|
62
107
|
Bug reports and pull requests are welcome on GitHub at https://github.com/madeindjs/active_storage-send_zip. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
63
108
|
|
64
|
-
## License
|
65
|
-
|
66
|
-
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
67
|
-
|
68
109
|
## Code of Conduct
|
69
110
|
|
70
111
|
Everyone interacting in the ActiveStorage::SendZip project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/madeindjs/active_storage-send_zip/blob/master/CODE_OF_CONDUCT.md).
|
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.email = ['contact@rousseau-alexandre.fr']
|
10
10
|
|
11
11
|
spec.summary = 'Create a zip from one or more Active Storage objects'
|
12
|
-
spec.description = '
|
12
|
+
spec.description = 'Add a `send_zip` method in your Rails controller to send a `.zip` file containing one (or many) ActiveStorage object(s)'
|
13
13
|
spec.homepage = 'https://github.com/madeindjs/active_storage-send_zip'
|
14
14
|
spec.license = 'MIT'
|
15
15
|
|
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'active_storage/send_zip/version'
|
2
|
-
require '
|
3
|
-
require 'zip'
|
4
|
-
require 'tempfile'
|
5
|
-
require 'pathname'
|
2
|
+
require 'active_storage/send_zip_helper'
|
6
3
|
|
4
|
+
# I `ActiveStorage` namespace to monkey-path my methods into it
|
7
5
|
module ActiveStorage
|
6
|
+
# This is an `ActiveSupport::Concern` to include into your controller.
|
7
|
+
# The purpose is just to add a `send_zip` method to your controller
|
8
8
|
module SendZip
|
9
9
|
extend ActiveSupport::Concern
|
10
10
|
|
@@ -16,76 +16,10 @@ module ActiveStorage
|
|
16
16
|
# @param filename [ActiveStorage::Attached::Many] files to save
|
17
17
|
def send_zip(active_storages, filename: 'my.zip')
|
18
18
|
require 'zip'
|
19
|
-
files = save_files_on_server active_storages
|
20
|
-
zip_data = create_temporary_zip_file files
|
19
|
+
files = SendZipHelper.save_files_on_server active_storages
|
20
|
+
zip_data = SendZipHelper.create_temporary_zip_file files
|
21
21
|
|
22
22
|
send_data(zip_data, type: 'application/zip', filename: filename)
|
23
23
|
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
# Download active storage files on server in a temporary folder
|
28
|
-
#
|
29
|
-
# @param files [ActiveStorage::Attached::Many] files to save
|
30
|
-
# @return [Array<String>] files paths of saved files
|
31
|
-
def save_files_on_server(files)
|
32
|
-
require 'zip'
|
33
|
-
# get a temporary folder and create it
|
34
|
-
temp_folder = Dir.mktmpdir 'active_storage-send_zip'
|
35
|
-
|
36
|
-
# count each files to avoid duplicates
|
37
|
-
filepaths = []
|
38
|
-
|
39
|
-
# download all ActiveStorage into
|
40
|
-
files.each do |picture|
|
41
|
-
filename = picture.filename.to_s
|
42
|
-
filepath = File.join temp_folder, filename
|
43
|
-
|
44
|
-
# ensure that filename not exists
|
45
|
-
if filepaths.include? filepath
|
46
|
-
# create a new random filenames
|
47
|
-
basename = File.basename filename
|
48
|
-
extension = File.extname filename
|
49
|
-
|
50
|
-
filename = "#{basename}_#{SecureRandom.uuid}#{extension}"
|
51
|
-
filepath = File.join temp_folder, filename
|
52
|
-
end
|
53
|
-
|
54
|
-
File.open(filepath, 'wb') { |f| f.write(picture.download) }
|
55
|
-
|
56
|
-
filepaths << filepath
|
57
|
-
end
|
58
|
-
|
59
|
-
filepaths
|
60
|
-
end
|
61
|
-
|
62
|
-
# Create a temporary zip file & return the content as bytes
|
63
|
-
#
|
64
|
-
# @param filepaths [Array<String>] files paths
|
65
|
-
# @return [String] as content of zip
|
66
|
-
def create_temporary_zip_file(filepaths)
|
67
|
-
temp_file = Tempfile.new('user.zip')
|
68
|
-
|
69
|
-
begin
|
70
|
-
# Initialize the temp file as a zip file
|
71
|
-
Zip::OutputStream.open(temp_file) { |zos| }
|
72
|
-
|
73
|
-
# open the zip
|
74
|
-
Zip::File.open(temp_file.path, Zip::File::CREATE) do |zip|
|
75
|
-
filepaths.each do |filepath|
|
76
|
-
filename = File.basename filepath
|
77
|
-
# add file into the zip
|
78
|
-
zip.add filename, filepath
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
return File.read(temp_file.path)
|
83
|
-
ensure
|
84
|
-
# close all ressources & remove temporary files
|
85
|
-
temp_file.close
|
86
|
-
temp_file.unlink
|
87
|
-
filepaths.each { |filepath| FileUtils.rm(filepath) }
|
88
|
-
end
|
89
|
-
end
|
90
24
|
end
|
91
25
|
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'rails'
|
2
|
+
require 'zip'
|
3
|
+
require 'tempfile'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
module ActiveStorage
|
7
|
+
# This module contains some methods usefull for `ActiveStorage::SendZip.send_zip`
|
8
|
+
# method.
|
9
|
+
module SendZipHelper
|
10
|
+
# Download active storage files on server in a temporary folder
|
11
|
+
#
|
12
|
+
# @param files [ActiveStorage::Attached::Many] files to save
|
13
|
+
# @return [Array<String>] files paths of saved files
|
14
|
+
def self.save_files_on_server(files)
|
15
|
+
require 'zip'
|
16
|
+
# get a temporary folder and create it
|
17
|
+
temp_folder = Dir.mktmpdir 'active_storage-send_zip'
|
18
|
+
|
19
|
+
if files.is_a? Array
|
20
|
+
return files.map { |file| save_file_on_server(file, temp_folder) }
|
21
|
+
elsif files.is_a? Hash
|
22
|
+
filepaths = []
|
23
|
+
|
24
|
+
files.each do |subfolder, filesHash|
|
25
|
+
filesHash.each { |f| filepaths << save_file_on_server(f, temp_folder, subfolder: subfolder) }
|
26
|
+
end
|
27
|
+
|
28
|
+
return filepaths
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Save the given file on the server
|
33
|
+
#
|
34
|
+
# @param file [ActiveStorage::Attached] files to save
|
35
|
+
# @param folder [String] where to store the file
|
36
|
+
# @return [String] the filepath of file created
|
37
|
+
def self.save_file_on_server(file, folder, subfolder: nil)
|
38
|
+
filename = file.filename.to_s
|
39
|
+
|
40
|
+
folder = File.join(folder, subfolder) unless subfolder.nil?
|
41
|
+
Dir.mkdir(folder) unless Dir.exist?(folder)
|
42
|
+
|
43
|
+
# build filepath & create path if not exists
|
44
|
+
filepath = File.join(folder, filename)
|
45
|
+
|
46
|
+
# Ensure that filename not already exists
|
47
|
+
if File.exist? filepath
|
48
|
+
# create a new random filenames
|
49
|
+
basename = File.basename filename
|
50
|
+
extension = File.extname filename
|
51
|
+
|
52
|
+
filename = "#{basename}_#{SecureRandom.uuid}#{extension}"
|
53
|
+
filepath = File.join folder, filename
|
54
|
+
end
|
55
|
+
|
56
|
+
File.open(filepath, 'wb') { |f| f.write(file.download) }
|
57
|
+
filepath
|
58
|
+
end
|
59
|
+
|
60
|
+
# Create a temporary zip file & return the content as bytes
|
61
|
+
#
|
62
|
+
# @param filepaths [Array<String>] files paths
|
63
|
+
# @return [String] as content of zip
|
64
|
+
def self.create_temporary_zip_file(filepaths)
|
65
|
+
temp_file = Tempfile.new('user.zip')
|
66
|
+
|
67
|
+
begin
|
68
|
+
# Initialize the temp file as a zip file
|
69
|
+
Zip::OutputStream.open(temp_file) { |zos| }
|
70
|
+
|
71
|
+
# open the zip
|
72
|
+
Zip::File.open(temp_file.path, Zip::File::CREATE) do |zip|
|
73
|
+
filepaths.each do |filepath|
|
74
|
+
filename = File.basename filepath
|
75
|
+
# add file into the zip
|
76
|
+
zip.add filename, filepath
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
return File.read(temp_file.path)
|
81
|
+
ensure
|
82
|
+
# close all ressources & remove temporary files
|
83
|
+
temp_file.close
|
84
|
+
temp_file.unlink
|
85
|
+
filepaths.each { |filepath| FileUtils.rm(filepath) }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_storage-send_zip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexandre Rousseau
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-12-
|
11
|
+
date: 2018-12-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,8 +52,8 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '10.0'
|
55
|
-
description:
|
56
|
-
|
55
|
+
description: Add a `send_zip` method in your Rails controller to send a `.zip` file
|
56
|
+
containing one (or many) ActiveStorage object(s)
|
57
57
|
email:
|
58
58
|
- contact@rousseau-alexandre.fr
|
59
59
|
executables: []
|
@@ -62,6 +62,7 @@ extra_rdoc_files: []
|
|
62
62
|
files:
|
63
63
|
- ".gitignore"
|
64
64
|
- ".travis.yml"
|
65
|
+
- CHANGELOG.yml
|
65
66
|
- CODE_OF_CONDUCT.md
|
66
67
|
- Gemfile
|
67
68
|
- Gemfile.lock
|
@@ -73,6 +74,7 @@ files:
|
|
73
74
|
- bin/setup
|
74
75
|
- lib/active_storage/send_zip.rb
|
75
76
|
- lib/active_storage/send_zip/version.rb
|
77
|
+
- lib/active_storage/send_zip_helper.rb
|
76
78
|
homepage: https://github.com/madeindjs/active_storage-send_zip
|
77
79
|
licenses:
|
78
80
|
- MIT
|