diff options
author | Go MAEDA <maeda@farend.jp> | 2020-03-21 05:59:31 +0000 |
---|---|---|
committer | Go MAEDA <maeda@farend.jp> | 2020-03-21 05:59:31 +0000 |
commit | ab47fb8ae0e6685900e3a22de3b9ce265a5b05fa (patch) | |
tree | 22a50ddb755864b883f02833b03db48feb072691 /app | |
parent | 6abf527aa0e3271ebd38c1ac50a4691dab611b2e (diff) | |
download | redmine-ab47fb8ae0e6685900e3a22de3b9ce265a5b05fa.tar.gz redmine-ab47fb8ae0e6685900e3a22de3b9ce265a5b05fa.zip |
Download all attachments at once (#7056).
Patch by Mizuki ISHIKAWA.
git-svn-id: http://svn.redmine.org/redmine/trunk@19601 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/attachments_controller.rb | 34 | ||||
-rw-r--r-- | app/helpers/attachments_helper.rb | 4 | ||||
-rw-r--r-- | app/models/attachment.rb | 25 | ||||
-rw-r--r-- | app/views/attachments/_links.html.erb | 5 | ||||
-rw-r--r-- | app/views/settings/_attachments.html.erb | 2 |
5 files changed, 68 insertions, 2 deletions
diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb index db90b55da..7e198d0bb 100644 --- a/app/controllers/attachments_controller.rb +++ b/app/controllers/attachments_controller.rb @@ -19,6 +19,8 @@ class AttachmentsController < ApplicationController before_action :find_attachment, :only => [:show, :download, :thumbnail, :update, :destroy] + before_action :find_container, :only => [:edit_all, :update_all, :download_all] + before_action :find_downloadable_attachments, :only => :download_all before_action :find_editable_attachments, :only => [:edit_all, :update_all] before_action :file_readable, :read_authorize, :only => [:show, :download, :thumbnail] before_action :update_authorize, :only => :update @@ -132,6 +134,20 @@ class AttachmentsController < ApplicationController render :action => 'edit_all' end + def download_all + Tempfile.create('attachments_zip-', Rails.root.join('tmp')) do |tempfile| + zip_file = Attachment.archive_attachments(tempfile, @attachments) + if zip_file + send_data( + File.read(zip_file.path), + :type => 'application/zip', + :filename => "#{@container.class.to_s.downcase}-#{@container.id}-attachments.zip") + else + render_404 + end + end + end + def update @attachment.safe_attributes = params[:attachment] saved = @attachment.save @@ -195,6 +211,11 @@ class AttachmentsController < ApplicationController end def find_editable_attachments + @attachments = @container.attachments.select(&:editable?) + render_404 if @attachments.empty? + end + + def find_container klass = params[:object_type].to_s.singularize.classify.constantize rescue nil unless klass && klass.reflect_on_association(:attachments) render_404 @@ -206,15 +227,24 @@ class AttachmentsController < ApplicationController render_403 return end - @attachments = @container.attachments.select(&:editable?) if @container.respond_to?(:project) @project = @container.project end - render_404 if @attachments.empty? rescue ActiveRecord::RecordNotFound render_404 end + def find_downloadable_attachments + @attachments = @container.attachments.select{|a| File.readable?(a.diskfile) } + bulk_download_max_size = Setting.bulk_download_max_size.to_i.kilobytes + if @attachments.sum(&:filesize) > bulk_download_max_size + flash[:error] = l(:error_bulk_download_size_too_big, + :max_size => bulk_download_max_size.to_i.kilobytes) + redirect_to back_url + return + end + end + # Checks that the file exists and is readable def file_readable if @attachment.readable? diff --git a/app/helpers/attachments_helper.rb b/app/helpers/attachments_helper.rb index 47e5ea78a..e496958bf 100644 --- a/app/helpers/attachments_helper.rb +++ b/app/helpers/attachments_helper.rb @@ -27,6 +27,10 @@ module AttachmentsHelper object_attachments_path container.class.name.underscore.pluralize, container.id end + def container_attachments_download_path(container) + object_attachments_download_path container.class.name.underscore.pluralize, container.id + end + # Displays view/delete links to the attachments of the given object # Options: # :author -- author names are not displayed if set to false diff --git a/app/models/attachment.rb b/app/models/attachment.rb index 6b8c75cc4..a89a0c37e 100644 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -19,6 +19,7 @@ require "digest" require "fileutils" +require "zip" class Attachment < ActiveRecord::Base include Redmine::SafeAttributes @@ -345,6 +346,30 @@ class Attachment < ActiveRecord::Base Attachment.where("created_on < ? AND (container_type IS NULL OR container_type = '')", Time.now - age).destroy_all end + def self.archive_attachments(out_file, attachments) + attachments = attachments.select{|attachment| File.readable?(attachment.diskfile) } + return nil if attachments.blank? + + Zip.unicode_names = true + archived_file_names = [] + Zip::File.open(out_file.path, Zip::File::CREATE) do |zip| + attachments.each do |attachment| + filename = attachment.filename + # rename the file if a file with the same name already exists + dup_count = 0 + while archived_file_names.include?(filename) + dup_count += 1 + basename = File.basename(attachment.filename, '.*') + extname = File.extname(attachment.filename) + filename = "#{basename}(#{dup_count})#{extname}" + end + zip.add(filename, attachment.diskfile) + archived_file_names << filename + end + end + out_file + end + # Moves an existing attachment to its target directory def move_to_target_directory! return unless !new_record? & readable? diff --git a/app/views/attachments/_links.html.erb b/app/views/attachments/_links.html.erb index 0a9f5e3eb..25d022029 100644 --- a/app/views/attachments/_links.html.erb +++ b/app/views/attachments/_links.html.erb @@ -5,6 +5,11 @@ :title => l(:label_edit_attachments), :class => 'icon-only icon-edit' ) if options[:editable] %> + <%= link_to(l(:label_download_all_attachments), + container_attachments_download_path(container), + :title => l(:label_download_all_attachments), + :class => 'icon-only icon-download' + ) if attachments.size > 1 %> </div> <table> <% for attachment in attachments %> diff --git a/app/views/settings/_attachments.html.erb b/app/views/settings/_attachments.html.erb index 818845e55..f0430e4a9 100644 --- a/app/views/settings/_attachments.html.erb +++ b/app/views/settings/_attachments.html.erb @@ -3,6 +3,8 @@ <div class="box tabular settings"> <p><%= setting_text_field :attachment_max_size, :size => 6 %> <%= l(:"number.human.storage_units.units.kb") %></p> +<p><%= setting_text_field :bulk_download_max_size, :size => 6 %> <%= l(:"number.human.storage_units.units.kb") %></p> + <p><%= setting_text_area :attachment_extensions_allowed %> <em class="info"><%= l(:text_comma_separated) %> <%= l(:label_example) %>: txt, png</em></p> |