fringd / zipline

A gem that lets you stream a zip file from rails
MIT License
297 stars 70 forks source link

zipline method not working from Grape API endpoint #106

Open sra-wtag opened 7 months ago

sra-wtag commented 7 months ago

I am using Grape for some of my APIs. I am trying to implement an export API. Now I am getting an error like: undefined method 'zipline' for #<Class:0x000000012385c270> in '/api/test/:id/export' endpoint

My API resource is:

class Test < Api
      # enable zipline
      include Zipline

      resource :test do
          get '/export' do
            files = JSON.parse Test.find(params[:id]).exportfiles
            zipline(files, "zip_file_name")
          end
      end
end
julik commented 4 months ago

Sadly Grape does not support ActionController methods, so zipline() won't work there. The Zipline module relies on a number of methods being available on ActionController and uses them. You need to do some work to wire zipline (and zip_kit) into Grape. I suspect it can be done somewhat like so (I doubt that JSON.parse in your code is appropriate, what does exportfiles return exactly?):

get '/export' do
  files_and_names = Test.find(params[:id]).exportfiles
  ZipKit::OutputEnumerator.streaming_http_headers.each_pair do |header_name, header_value|
    header(header_name, header_value)
  end
  enum = ZipKit::OutputEnumerator.new do |zip_kit_streamer|
    handler = Zipline::ZipHandler.new(zip_kit_streamer, Rails.logger)
    files_and_names.each do |file, name, options = {}|
      handler.handle_file(file, name.to_s, options)
    end
  end

  Grape::ServeStream::StreamResponse.new(enum)
end

Basically, you need to find a way to serve a standard Rack enumerable body using Grape. You might want to inquire in Grape support channels on how to do this (I never used Grape myself) - https://github.com/ruby-grape/grape?tab=readme-ov-file#project-resources