diff options
author | Go MAEDA <maeda@farend.jp> | 2020-04-11 07:58:01 +0000 |
---|---|---|
committer | Go MAEDA <maeda@farend.jp> | 2020-04-11 07:58:01 +0000 |
commit | ea54e1acdbc763b543afec7dc1b344cc45df3b23 (patch) | |
tree | bbb57300bf694aaeda24f7d5c90f1a8bfb8c0ed7 /app | |
parent | 62c7da1b3f97815a05c5522fde799affb9708e2a (diff) | |
download | redmine-ea54e1acdbc763b543afec7dc1b344cc45df3b23.tar.gz redmine-ea54e1acdbc763b543afec7dc1b344cc45df3b23.zip |
Fix that bulk download raises Errno::EACCES on Windows (#7056).
Patch by Yuichi HARADA.
git-svn-id: http://svn.redmine.org/redmine/trunk@19688 e93f8b46-1217-0410-a6f0-8f06a7374b81
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/attachments_controller.rb | 20 | ||||
-rw-r--r-- | app/models/attachment.rb | 13 |
2 files changed, 18 insertions, 15 deletions
diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb index b69dcf983..0c76490b2 100644 --- a/app/controllers/attachments_controller.rb +++ b/app/controllers/attachments_controller.rb @@ -137,16 +137,16 @@ class AttachmentsController < ApplicationController 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 + zip_data = Attachment.archive_attachments(@attachments) + if zip_data + file_name = "#{@container.class.to_s.downcase}-#{@container.id}-attachments.zip" + send_data( + zip_data, + :type => Redmine::MimeType.of(file_name), + :filename => file_name + ) + else + render_404 end end diff --git a/app/models/attachment.rb b/app/models/attachment.rb index b5a3332ac..b0cc94cb2 100644 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -346,28 +346,31 @@ 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) + def self.archive_attachments(attachments) attachments = attachments.select(&:readable?) return nil if attachments.blank? Zip.unicode_names = true archived_file_names = [] - Zip::File.open(out_file.path, Zip::File::CREATE) do |zip| + buffer = Zip::OutputStream.write_buffer do |zos| 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) + basename = File.basename(attachment.filename, extname) filename = "#{basename}(#{dup_count})#{extname}" end - zip.add(filename, attachment.diskfile) + zos.put_next_entry(filename) + zos << IO.binread(attachment.diskfile) archived_file_names << filename end end - out_file + buffer.string + ensure + buffer&.close end # Moves an existing attachment to its target directory |