2012-03-26 3 views
4

Rails 3.2.2 앱에서 스트리밍 CSV 다운로드를 실행하려면 필사적입니다.스트리밍 CSV를 Rails 3.2 앱에서 다운로드

이 기능에 대한 지원을 알리는 'csv_builder'gem (https://github.com/dasil003/csv_builder)을 사용해 보았지만 Rails 3.2에서 변경된 사항이 작동하지 않는 것으로 보입니다 (그것은 응용 프로그램 시작시 '초기화되지 않은 상수 ActionView :: Template :: Handler'오류를 생성합니다.)

다른 아이디어 나 해결책이 있습니까? 감사!

편집 : 명확히하기 위해 모델의 모든 항목을 CSV 파일로 내 보내야합니다. 시간이 너무 많이 걸리므로 스트리밍이 필요합니다. 나는 이것을 위해 Comma gem (https://github.com/crafterm/comma)을 과거에 사용했지만 아직 스트리밍을 지원하지 않는다.

+0

달성하려는 목표는 무엇입니까? 일부 샘플 코드가 도움이 될 수 있습니다. – Yule

+0

고마워요 ... 위의 편집을 참조하십시오 –

답변

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

+0

이 코드는 동일한 코드를 사용하여 Rails 3.2.1에서 작동하게하려고합니다. unicorn 설정에서 "listen 3000, tcp_nopush => false"를 넘어 뭔가가 있습니까? 위에 게시 한 코드 이외의 다른 부분이 누락되었을 수 있습니다. 추가 통찰력은 대단하고 감사 할 것입니다. – Blastula

+0

Rack :: ETag를 사용한 경우 ETag에서 응답을 버퍼하지 못하도록 다음 행을 추가해야합니다. self.response.headers [ "Last-Modified"] = Time.now.to_s – etiennepeiniau

0

레일스 2.3.8 응용 프로그램에서 취한 접근법은 새 스레드를 생성하여 csv 구문 분석을 처리 한 다음 AJAX 호출을 사용하여 서버가 파일 준비 상태인지 확인합니다 (파일을 사용했는지 확인하는 것). mtime).

그냥 내가 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