0

I'm trying to make a request to a Rails controller method that responds with a zipped file. How to I make the frontend Axios request?

Controller method:

include ActionController::Streaming
include Zipline

def index
  respond_to do |format|
    format.zip do
      zipline([[@project.attached.url, "#{@project_name.parameterize}.pdf"]], "documents.zip")
    end
  end
end

What I would do if I were using a view:

= link_to "Download projects", company_projects_path(@company, format: :zip)

What would the equivalent axios request look like? This does not work:

  const handleClick = () => {
    axios
    .get(`/projects/${project.id}`, {
      headers: { 'Accept': 'application/zip' }
    })
    .catch(e => console.log(e))
  };
Hughes
  • 366
  • 4
  • 13
  • When you are replying to a format that should be downloaded (pdf, zip etc) you want to use [`send_file`](https://api.rubyonrails.org/v5.2.4.4/classes/ActionController/DataStreaming.html#method-i-send_file) to set the correct response headers. I have no idea why you would really want to "render" a zip as a group of files is not really something you would render with a view. I would use a service object or something that just returns a tempfile or file handle that your controller uses and which does the actual job of gathering up the files to be zipped. – max Dec 22 '20 at 16:41
  • The correct mime type is also `application/zip`. – max Dec 22 '20 at 16:45
  • Right, thanks max, the method name was confusing the issue. I've updated the question. I'm using zipline to gather the files. – Hughes Dec 22 '20 at 16:52
  • Sorry to be a hassle but why zip if its just a single file? Both zip and gzip use the DEFLATE algorithm but almost every browser in existence can handle GZIP compression seamlessly on the transport layer. Just use Rack::Deflater instead which wont require your users to pointlessly unpack a zip file on their end. https://thoughtbot.com/blog/content-compression-with-rack-deflater – max Dec 22 '20 at 16:59
  • No worries. So in this example it's 1 file, but I would be zipping up a couple as a requirement. Thanks for the link, I'll have a read. I've solved the issue by just using an anchor tag. – Hughes Dec 22 '20 at 17:32

1 Answers1

0

So I found this worked for me:

<a href={`/projects/${project.id}.zip`} download>Download all</a>

Instead of using a button with an onClick axios request that would stream a zipped file to it - which makes no sense - simply creating an anchor tag that has a link to the zip path will download it.

As max pointed out headers: { 'Accept': 'application/zip' } would be the correct format to access it, but it doesn't make sense doing this.

EDIT:

Checkout this answer. The browser will throw an error Resource interpreted as Document but transferred with MIME type application/zip.

Hughes
  • 366
  • 4
  • 13