fix(export): sanitize filename containing unsafe chars for storage

Pourrait fixer des problèmes de dezip sous windows de zip.
This commit is contained in:
Colin Darie 2023-05-04 12:55:05 +02:00
parent f615facbba
commit 5be8865675
No known key found for this signature in database
GPG key ID: 4FB865FDBCA4BCC4
2 changed files with 33 additions and 8 deletions

View file

@ -8,7 +8,7 @@ module DownloadManager
def initialize(attachments, destination)
@attachments = attachments
@destination = destination
@destination = Pathname.new(destination)
end
def download_all
@ -28,21 +28,22 @@ module DownloadManager
# can't be used with typhoeus, otherwise block is closed before the request is run by hydra
def download_one(attachment:, path_in_download_dir:, http_client:)
attachment_path = File.join(destination, sanitize_filename(path_in_download_dir))
attachment_dir = File.dirname(attachment_path)
path = Pathname.new(path_in_download_dir)
attachment_path = destination.join(path.dirname, sanitize_filename(path.basename.to_s))
attachment_path.dirname.mkpath # defensive, do not write in undefined dir
FileUtils.mkdir_p(attachment_dir) if !Dir.exist?(attachment_dir) # defensive, do not write in undefined dir
if attachment.is_a?(ActiveStorage::FakeAttachment)
File.write(attachment_path, attachment.file.read, mode: 'wb')
attachment_path.write(attachment.file.read, mode: 'wb')
else
request = Typhoeus::Request.new(attachment.url)
request.on_complete do |response|
if response.success?
File.open(attachment_path, mode: "wb") do |fd|
attachment_path.open(mode: "wb") do |fd|
fd.write(response.body)
end
else
File.delete(attachment_path) if File.exist?(attachment_path) # -> case of retries failed, must cleanup partialy downloaded file
attachment_path.delete if attachment_path.exist? # -> case of retries failed, must cleanup partialy downloaded file
on_error.call(attachment, path_in_download_dir, response.code)
end
end
@ -52,7 +53,9 @@ module DownloadManager
private
def sanitize_filename(filename)
def sanitize_filename(original_filename)
filename = ActiveStorage::Filename.new(original_filename).sanitized
return filename if filename.bytesize <= 255
ext = File.extname(filename)

View file

@ -51,5 +51,27 @@ describe DownloadManager::ParallelDownloadQueue do
expect(attachment.file.read).to eq(File.read(target))
end
end
context 'with filename containing unsafe characters for storage' do
let(:destination) { "file:éà\u{202e} K.txt" }
it 'sanitize the problematic chars' do
target = File.join(download_to_dir, 'file-éà- K.txt')
expect { subject }.to change { File.exist?(target) }
attachment.file.rewind
expect(attachment.file.read).to eq(File.read(target))
end
context 'with a destination tree' do
let(:destination) { 'subdir/file.txt' }
it 'preserves the destination tree' do
target = File.join(download_to_dir, 'subdir/file.txt')
expect { subject }.to change { File.exist?(target) }
attachment.file.rewind
expect(attachment.file.read).to eq(File.read(target))
end
end
end
end
end