I'm using rails 6.1 and paperclip 5.0
I built a worker to generate a ZIP file based on other stored files in S3 then upload this ZIP file back to S3.
So basically I download the files from S3 add them in this Temp ZIP and then saving the ZIP to S3.
class Download < ApplicationRecord
# ...
has_attached_file :file,
path: "#{ENV['DEVELOPER']}/Institucion-:institution_id/Usuario-:user_id/:id/:filename",
content_type: { content_type: ["application/zip"] }
# ...
end
class GenerateZipWorker < ApplicationWorker
def perform(download_id, options = {})
@download = Download.find(download_id)
# ...
@download.file = generate_full_zip
# Here the ZIP Temp file gets a PDF content-type
# @download.file.content_type
# => "application/pdf"
@download.file_file_name = "#{@postulation_template.name[0..100].parameterize}.zip"
@download.save
end
private
def generate_full_zip
temp_zip_file = Tempfile.new("#{@postulation_template.name[0..100].parameterize}.zip")
Zip::File.open(temp_zip_file.path, Zip::File::CREATE) do |zip|
@postulations.each do |postulation|
generate_postulation_file(zip, postulation)
end
end
temp_zip_file.rewind
temp_zip_file
end
def generate_postulation_file(zip, postulation)
root_path = postulation.file_name
zip.get_output_stream(File.join(root_path, postulation.postulation_pdf_file_name)) { |f| f.write postulation.postulation_pdf.s3_object.get.body.string }
end
end
I tried to set manually the content-type before saving the file
@download.file_content_type = 'application/zip'
But when I download the file from the AWS S3 dashboard it downloads it as a PDF, adding a .pdf
at the end of the file name (foo.zip.pdf
). If I delete the PDF extention keeping the .zip the downloaded file works just fine.
If I change the content-type from the AWS S3 dashboard from application/pdf
to application/zip
I can download with no issues.
1️How can I upload the file content-type as application/zip
?
2️⃣Is it the Temp file messing the content-type
?
3️⃣Is there a better way to build the ZIP temp file?
Apparently Paperclip incorrectly detects MIME type of the file.
You correctly tried to manually set content type before saving it but it did not work for you because Paperclip actually reads content type from a different object.
If you're interested, you can check the source files of Paperclip.
The Attachment instance has @file
instance variable created on it, which in its turn has @content_type
instance variable, and this is from where Paperclip reads the content type before it uploads it to S3.
So, what should fix it for you is to do the following:
@download.file_content_type = 'application/zip'
@download.file.instance_variable_get(:"@file").instance_variable_set(:"@content_type", "application/zip")
@download.save
You can check that before you update the instance variable as I specified this code should return application/pdf
(even if you updated @download.file_content_type
):
@download.file.instance_variable_get(:"@file").content_type
After you set the var as I wrote then this will return application/zip
as expected.