Search code examples
ruby-on-railsrubypdfamazon-s3zip

Ruby ZIP Temp file hast PDF content-type


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.enter image description here

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?


Solution

  • 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.