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