alissa 发表于 2013-1-22 22:36:47

ajax下载后台任务执行生成的csv文件

点击一个按钮,生成一份csv文件,这个csvs生成过程很耗时,要放到后台执行,生成完了之后,还要把文件发送到客户端,这个采用ajax定时请求,去判断文件是否生成成功
1、页面上按钮
<%= button_to_remote "CSV", {:url => {:action => 'get_csv'},
                              :confirm => "Are u sure?"},
                              :class => "btn_red" %>
2、接受请求的action
def get_csv
    spawn do# backgroud job
      begin
      # generating csv
      # more code here
      rescue Exception => e
      pp e
      Rails.cache.write("csv_#{Process.pid}", 'error')
      Rails.cache.write("csv_#{Process.pid}_error", e)
      return
      end
      
      # mark the csv generated completed
      Rails.cache.write("csv_#{Process.pid}", true)
    end
   
    flash[:notice] = "Generating csv"
    render :update do |page|
      page.replace_html "promote", :partial => "/common/messages"
      page.insert_html :top,
                     "progress_ajax",
                        periodically_call_remote(:url => {:action => "csv_task_progress"},
                                                 :frequency => 5)
    end
end

3、定时请求的js和action
def periodically_call_remote(options = {})
   variable = options[:variable] ||= 'poller'
   frequency = options[:frequency] ||= 10
   code = "#{variable} = new PeriodicalExecuter(function()
{#{remote_function(options)}}, #{frequency})"
   javascript_tag(code)
end

def csv_task_progress
    if Rails.cache.read("csv_#{Process.pid}").eql?('error')
      # csv generating occurred error
      Rails.cache.write("sbps_#{Process.pid}", nil)
      flash[:error] = Rails.cache.read("csv_#{Process.pid}_error")
      render :update do |page|
      page << "poller.stop();"
      page.replace_html "promote", :partial => "/common/messages"
      end
      return
    elsif Rails.cache.read("csv_#{Process.pid}").blank?
      # return if the csv file have not generated completely
      return (render :text => nil)
    end
    # prevent the later request download csv
    Rails.cache.write("csv_#{Process.pid}", false)
    flash[:notice] = "CSV Generated yet"
    download_url = "/admin/exact_count/download_csv"
    render :updatedo |page|
      js = <<-EOF
      poller.stop(); // stop the periodically call
      var elemIF = document.createElement("iframe");
      elemIF.src = '#{download_url}';
      elemIF.style.display = "none";
      document.body.appendChild(elemIF);
      EOF
      page << js
      page.replace_html "promote", :partial => "/common/messages"
    end
end

4、下载csv的action
def download_csv
    send_file("#{RAILS_ROOT}/tmp/csv.csv", :type=>'text/csv', :filename=>"csv.csv")
end

至此就可以完成这个需求了
页: [1]
查看完整版本: ajax下载后台任务执行生成的csv文件