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.

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
Bulma Logo

Have a Project in mind?