summaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authorGo MAEDA <maeda@farend.jp>2020-04-11 07:58:01 +0000
committerGo MAEDA <maeda@farend.jp>2020-04-11 07:58:01 +0000
commitea54e1acdbc763b543afec7dc1b344cc45df3b23 (patch)
treebbb57300bf694aaeda24f7d5c90f1a8bfb8c0ed7 /app
parent62c7da1b3f97815a05c5522fde799affb9708e2a (diff)
downloadredmine-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.rb20
-rw-r--r--app/models/attachment.rb13
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