2011-12-28 77 views
3

我正在處理我的第一個應用程序,我需要一些幫助,允許我的用戶下載帶有某些正在顯示在頁面上的變量的文本文件。如何創建臨時文件並寫入,然後允許用戶下載它?

以購物清單爲例。 假設您允許您的用戶創建產品購物清單,然後顯示包含購物清單頁面上的項目的購物清單,例如
本地主機:3000 /表/我的列表


看看下面的示例代碼(這可能是不正確的):

File.open('shopping_list.txt', 'w') do |file| 
    file.puts 'Item 1: #{product_1.name}' 
    file.puts 'Item 2: #{product_2.name}' 
    file.puts 'Item 3: #{product_3.name}' 
end 



然後將創建具有一個文本文件以下內容:

Item 1: Eggs 
Item 2: Butter 
Item 3: Bread 

然後
用戶應該能夠下載該文件(我不希望這個文件是ST通過下載鏈接進入服務器)。

我不知道如何做到這一點,但我希望你們能指導我。 :d


TL; DR

  • 創建模型數據填充的文本文件
  • 文本文件不應該被存儲在服務器上,但創建(也許創建實現這個方法?)因爲用戶點擊下載按鈕(不知道這是否是軌道方式,但也許有人可以告訴我更好的方式)

回答

7

我假設有對List與屬性name作爲列表的名稱的資源並有一個屬性description

首先列表has_many項目,創建一個下載路徑更改路線config/routes.rb

resources :lists do 
    member {get "download"} 
end 

現在,如果運行在控制檯rake routes你應該看到像

/lists/:id/download 

路線什麼是更多,你現在應該有傭工download_list_url & download_list_path在視圖中使用像

<ul> 
<% @lists.each do |list| %> 
    <li> <%= list.name %> - <%= link_to 'Download List', download_list_path(list) %> </li> 
<% end %> 
</ul> 

在你的lists_controller添加動作,並且因爲你實際上並不想保留在服務器磁盤上的文件只是strea米的數據作爲一個字符串

def download 
    list = List.find(params[:id]) 
    send_data list.as_file, 
    :filename => "#{list.name}.txt", 
    :type => "text/plain" 
end 

最後你看,我已經使用了as_file方法,你應該添加到模型中(我不想做這個東西在控制器,脂肪模型,瘦控制器)。所以在List模型

def as_file 
    output = [self.name] 
    self.items.each {|item| output << item.description } 
    output.join("\n") 
end 
+0

這工作就像一個魅力!你搖滾男人! – imjp 2012-01-07 04:52:59

+0

你能否幫我解決一個快速問題,我修改了你的代碼?我想創建類似這樣的要點,但不知道如何實現:https://gist.github.com/1573917 - 基本上我需要能夠爲每行輸入不同的值,但我不確定如何實現這一點。 – imjp 2012-01-07 05:48:07

+0

希望https://gist.github.com/1582262有幫助,我不完全確定協會(如果有的話)看着你的要點。 – Bangline 2012-01-09 09:57:00

1

您可以嘗試TempFile和send_file的組合。在你的控制器的行動..

file = Tempfile.new('foo') 
file.write("hello world") 
file.close 

send_file file.path 
+0

感謝您的回覆。在我看來,如何鏈接到這個生成的文件?另外,我可以在一個方法中傳遞ruby代碼來爲我的用戶動態創建文件嗎? – imjp 2011-12-28 23:19:06

+0

Download Jamsi 2012-02-05 23:12:38

3

你說你不想存儲在服務器上的文件,但「請求」下載請求;這聽起來像你只是想生成和提供一個文本文件來響應下載鏈接。有幾種方法,但你想確保設置MIME類型,以便瀏覽器將其視爲文本文件而不是HTML文檔。

product_info = [ 
    "Item 1: #{product_1.name}", 
    "Item 2: #{product_2.name}", 
    "Item 3: #{product_3.name}", 
    ].join("\n") 

render :text => product_info # implies :content_type => Mime::Type["text/plain"] 

順便說一句,上面的open/puts的例子不會輸出你認爲的單引號字符串不插入的內容。

+0

哦,我認爲他們會像插入紅寶石一樣插入。我正在閱讀這本紅寶石書,並嘗試了它,它似乎工作正常。它創建了帶引號等的文件 – imjp 2011-12-28 23:28:54

+0

在irb中試試這個:'foo ='bar'; puts'+#{foo} +',「+#{foo} +」';你會得到「+#{foo} + \ n + bar +」。第一行沒有插入foo,因爲字符串是單引號的。 – dbenhur 2011-12-28 23:41:02

+0

這些評論都不能幫助我在實現目標方面取得進展:(你知道我能找到一些幫助來解決這個問題的例子嗎?就像這個例子的整個代碼一樣,我很驚訝railscasts.com沒有創建文件創建 – imjp 2011-12-29 02:26:19

3

所以,你想:

  • create text files populated with model data (perhaps create a method to achieve this?)
  • text files should not be stored on the server, but created as users click the download button (not sure if this is the rails way but perhaps someone could show me a better way)

你有正確的想法,這裏是做什麼:

  1. 在創建方法您模型來生成文本文件的內容。假設這種方法叫list_data

  2. 看起來好像你有一個現存的控制器動作my_list。因此,我們可以在控制器中調用我們的新方法,如下所示:

def my_list 
    # pre-existing code 
    respond_to do |format| 
    format.html # show html page as before 
    format.text do 
     send_data @list.list_data, :content_type => 'text/plain', :filename => 'my-shopping-list.txt' 
    end 
    end 
end 

要鏈接到下載,只需要使用

http://api.rubyonrails.org/classes/ActionController/DataStreaming.html#method-i-send_data全文檔上send_data

買者&說明:使用上面的方法,有沒有真正的文件明確創建,Rails正在爲您提供流媒體服務。因此,此方法不適用於非常大的文件,或者文件內容的生成需要一段時間。使用延遲的方法來生成文件並將其存儲 - 如果是這種情況,文件內容在某處 - 但是我們可以在生成文件後使用send_data

+0

文件大小將會非常小,因爲它不會成爲一個實際的購物清單 – imjp 2012-01-07 04:23:32

+0

哪裏需要放置'my_list'方法?Controller,model or helper?I已經嘗試了所有3,但得到錯誤。 – imjp 2012-01-07 04:40:14

+1

@imjp在控制器:)我看你已經解決了它。祝你好運在你的旅程 – 2012-01-07 05:43:14

0

在Rails 2.3中,您可以使用Template Streaming。與Redmine合作我可以記得那樣的事情,你必須適應你的情況。參考:Streaming and file downloads

require "prawn" 
class ClientsController < ApplicationController 

    # Generate a PDF document with information on the client and return it. 
    # The user will get the PDF as a file download. 
    def download_pdf 
    client = Client.find(params[:id]) 
    send_data(generate_pdf, :filename => "#{client.name}.pdf", :type => "application/pdf") 
    end 

private 

    def generate_pdf(client) 
    Prawn::Document.new do 
     text client.name, :align => :center 
     text "Address: #{client.address}" 
     text "Email: #{client.email}" 
    end.render 
    end 

end 

使用通瓜,你必須只改變「CONTENT_TYPE」參數:

def my_list 
    # pre-existing code 
    respond_to do |format| 
    format.html # show html page as before 
    format.text do 
     send_data @list.list_data, :content_type => 'text/plain', :filename => 'my-shopping-list.txt' 
    end 
    end 
end 
相關問題