2012-03-26 49 views
4

我迫不及待想要在我的Rails 3.2.2应用中使用流式CSV下载工作。从Rails 3.2应用流式CSV下载

我试过了'csv_builder'gem(https://github.com/dasil003/csv_builder),它宣传了对这个功能的支持,不过看起来Rails 3.2中有一些改变使它不能工作(它会在应用程序启动时产生'未初始化的常量ActionView :: Template :: Handler'错误)。

其他想法或解决方案吗?谢谢!

编辑:澄清,我需要导出模型的所有条目作为CSV文件。有很多行,它是超时的......因此需要流式传输。我过去曾使用过逗号(https://github.com/crafterm/comma),但目前它也不支持流式传输。

+0

你想达到什么目的?一些示例代码可能会有所帮助。 – Yule 2012-03-26 15:54:11

+0

谢谢......看看我上面的编辑 – 2012-03-26 16:02:10

回答

7

好的,经过多一点的研究,我在控制器中一起攻击了以下内容。它会流如果response_body给予一些可枚举的(是一个单词?)。此外,服务器需要能够流(我在Heroku上使用Unicorn)。我非常希望在控制器中没有所有这些东西,所以我的下一步是以某种方式提取它。

format.csv { 
    @entries = Entry.all 
    @columns = ["First Name", "Last Name"].to_csv 
    @filename = "entries-#{Date.today.to_s(:db)}" 

    self.response.headers["Content-Type"] ||= 'text/csv' 
    self.response.headers["Content-Disposition"] = "attachment; filename=#{@filename}" 
    self.response.headers["Content-Transfer-Encoding"] = "binary" 

    self.response_body = Enumerator.new do |y| 
     @entries.each_with_index do |entry, i| 
     if i == 0 
      y << @columns 
     end 
     y << [entry.first_name, entry.last_name].to_csv 
     end 
    end 
    } 
+0

你能否提供完整的控制器定义只是为了确保 – Jonathan 2012-04-18 22:41:39

+0

这只是试图让我使用相同的代码来使用Rails 3.2.1。除了“listen 3000,:tcp_nopush => false”之外,还有什么可以使用独角兽配置吗?除了上面发布的代码之外,我可能会遗漏任何其他内容吗?任何额外的洞察力将是真棒,非常感谢。 – Blastula 2012-05-31 19:05:09

+0

如果您使用Rack :: ETag,则需要添加以下行以防止ETag缓冲响应:self.response.headers [“Last-Modified”] = Time.now.to_s – etiennepeiniau 2012-11-04 18:35:31

0

我使用Rails 2.3.8应用程序的方法是产生一个新线程来处理csv解析,然后使用AJAX调用来检查服务器以查看文件是否准备就绪(我依赖于File。修改时间)。

刚撕开它的应用程序,以便张贴在这里我已经删除很多的CSV解析代码的,并没有包括所有的意见

一天繁忙的遗憾结束:d

控制器/ exports_controller.rb

class ExportsController < ApplicationController 
      require 'fastercsv' 
      require 'generic_agent' 
      require 'generic_record' 

     def listing 

      @this_filepath = "../html/whatever/" << Time.now.strftime("%I:%M:%S_%d:%m:%y") << ".csv" 

      @spawn_id = spawn(:nice => 1) do 

      FasterCSV.open(@this_filepath, "w") do |csv| 

       csv << [ "outbreak_id"] 
      end 

      end 

      render :update do |page| 
      page.replace_html 'export_status', :partial => 'export_status_partial' 
      end 

     end 

    def send_export 

    @this_filepath = params[:with] 
    csv_file = File.open(@this_filepath.to_s, 'r') 

    csv_string = "" 
    csv_file.each_line do |line| 
     csv_string << line 
    end 

    send_data csv_string, :filename => "export.csv", 
       :type => 'text/csv; charset=iso-8859-1; header=present', 
       :disposition => "attachment; filename=export.csv" 
       #send_file @this_filepath.to_s, :stream => false, :type=>"text/csv", :x_sendfile=>true 

       #send_data csv_string, :filename => export.csv 

       #File.delete(@this_filepath.to_s) 
    end 

    def export_checker 
    filename_array = params['filename'].split(/\//) 
       @file_found = 0 
       @file_ready = 0 

       @file_size = File.size(params['filename']) 
       @this_filepath = params['filename'] 

       if File.exists?(params['filename']) 
       release_time = Time.now - 5.seconds 
       if File.mtime(params['filename']).utc < release_time.utc 

       @file_found = 1 
       @file_ready = 1 
       @file_access_time = File.mtime(params['filename']) 
       @file_release_time = release_time 
       @file_size = File.size(params['filename']) 

       else 
       @file_found = 1 
       @file_ready = 0 
       @file_size = File.size(params['filename']) 

       end 

       else 

       @file_found = 0 
       @file_ready = 0 
       @file_size = File.size(params['filename']) 

       end 

    render :action => "export_checker" 
    end 
end 

视图/出口/ export_checker.rjs

if @file_found == 1 && @file_ready == 1 && @file_size > 0 


page.replace_html 'link_to_file', :partial => "export_ready" 
if @file_release_time 
page.replace_html 'notice', "<div>Completed #{@file_release_time.strftime("%I:%M:%S %A %d %B %Y")} :: file size #{@file_size.to_s}</div>" 
end 

page.visual_effect :highlight, 'link_to_file', :endcolor => '#D3EDAB' 

elsif @file_found == 1 
page.replace_html 'link_to_file', "<div> File found, but still being constructed.</div><div>#{@this_filepath.to_s}</div>" 
page.visual_effect :highlight, 'link_to_file', :endcolor => '#FF9900' 
else 
page.replace_html 'link_to_file', "<div> File not found @file_found #{@file_found.to_s} @file_ready #{@file_ready.to_s}</div>" 
page.visual_effect :highlight, 'link_to_file', :endcolor => '#FF0000' 
end