How to send a file in the response via Grape API in Rails

How to send a file as a response in the API using Ruby on Rails using Grape API framework. Download file in response for Grape API framework.

Posted by Ameena on 16 Apr 2020

Consider reading this blog if you are wondering how to send a file as a response in the API using Ruby on Rails.

As an example, I have considered sending a zip file for which I have used a gem rubyzip

After you have a file ready that needs to be sent, you will have to describe three things in your code for Rails to understand what needs to be sent to the recipient.

Content-Type

HTTP response that we are sending should include the Content-Type header field which indicates the media type of the body.

Content-Disposition

HTTP response should include the Content-Disposition response header that indicating if the content is expected to be displayed inline in the browser, or as an attachment.

API format

The API to support the :binary content-types. By using :binary there will be no formatter, data will be returned "as is".

# users.rb
...
get :zipped_media_files do
  user = User.find(params[:id])
  directory_to_zip = "#{Rails.root}/tmp/#{user.full_name}"
  Dir.mkdir(directory_to_zip)
  zip_file_name = "#{Rails.root}/tmp/#{user.full_name}.zip"
  user.file_attachments.each do |file_attachment|
    url = file_attachment.file.url
    file_path = url.match(/\.com\/([^\?]*)/)[1]
    file_name = File.basename(file_path)
    File.open("#{Rails.root}/tmp/#{user.full_name}/#{file_name}", "wb") do |f|
      f << open(url).read
    end
  end
  files = Dir.entries(directory_to_zip) - %w( . .. )
  Zip::File.open(zip_file_name, ::Zip::File::CREATE) do |zipfile|
    files.each do |file|
      zipfile.add(file, "#{Rails.root}/tmp/#{user.full_name}/#{file}")
    end
  end
  content_type "application/octet-stream"
  header['Content-Disposition'] = "attachment; filename=#{user.full_name}.zip"
  env['api.format'] = :binary
  File.open(zip_file_name, 'rb').read
end

Keep Coding !!!

Contact us to work on your website.

- Ameena


We support the Open Source community.



VueJS Logo

Have a Project in mind?