rails 文件下載相關操作的一些總結


用rails寫一些內部工具的時候, 以前遇到文件下載的相關需求的時候, 都是直接把文件生成到 /public 下面, 但是遇到需要即時生成一堆文件的時候, 這種方式就比較悲劇了, 

比如需求要求生成一堆文件, 要一起下載只能生成以后, ZIP 壓縮成一個包下載, 但是如果利用文件系統來存儲, 管理這些數據, 文件生成一堆不說, 光各種 mv, cp, zip操作就夠煩人的了。

 

rails 提供了很多有用的API來完成文件下載的功能:

1. send_data, send_file 用於文件的下載send_data(data, options = {})send_file(path, options = {})這2個的區別在於是否在文件系統中生成文件, 應該send_file就是send_data包了一層, 多了從文件系統讀取文件這個操作。


send_file例子:
IMAGES_PATH = File.join(Rails.root, "public", "images") def download send_file(File.join(IMAGES_PATH, "image.jpg")) end

send_data的一些說明:
send_data的選項有4個,:filename, :type, :disposition, :status
:type是發送文件的資源類型, jpeg格式圖片: "image/jpeg", docx文檔: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
:disposition有2個值:inline或:attachment, 這決定了瀏覽器的打開方式, 是下載還是在瀏覽器中打開

send_data例子:
send_data zip_data, filename: "#{file_name}.zip", type: 'application/zip', :disposition => 'attachment'

一些額外的說明:
字符串的 force_encoding 會改變源數據的解釋方式, 不過並不會改變源數據, 但是在ruby 1.9 里面發送數據需要force_encoding('BINARY'), 
但是我在2.x 里面沒用這個文件也發送成功了, 沒出什么問題。
a = "Ü" a.bytes.to_a #=> [195, 156] a.chars.to_a #=> ["Ü"] a.force_encoding("BINARY") a.bytes.to_a #=> [195, 156] a.chars.to_a #=> ["\xC3", "\x9C"

2. 生成csv文件不經過文件系統, 直接用 send_data 來發送到客戶端
ruby 的CSV庫, 2種方式生成csv文件, 第一種方式生成了 csv 文件后直接保存到文件系統中, 第二種方式直接生成一個csv_string。
這個時候就可以用send_data直接發送數據了。
CSV.open("path/to/file.csv", "wb") do |csv| csv << ["row", "of", "CSV", "data"] csv << ["another", "row"] # ... end
csv_string = CSV.generate do |csv| csv << ["row", "of", "CSV", "data"] csv << ["another", "row"] # ... end
send_data csv_string, :filename => '你看見了一個csv文件.csv', :type => "text/comma-separated-values", :disposition => "attachment"

3. 生成csv文件, 直接生成ZIP文件, 直接用 send_data 發送到客戶端
    compressed_filestream = Zip::OutputStream.write_buffer(::StringIO.new('')) do |zos|
      zos.put_next_entry "第一個文件的名字"
      zos.print File.read('path')
      
      zos.put_next_entry "第二個文件的名字"
      zos.print file_string
    end

    compressed_filestream.rewind
    return compressed_filestream.read

  然后返回的數據直接用send_data發送就好了:

 send_data zip_data, filename: "#{file_name}.zip", type: 'application/zip', :disposition => 'attachment'



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM