2011-02-04 37 views
6

我目前正試圖直接從zip文件將圖像文件附加到模型(即沒有先將它們保存到磁盤上)。看來應該有一種更清晰的方式來將ZipEntry轉換爲Tempfile或File,它可以存儲在內存中以傳遞給另一個知道如何處理它的方法或對象。如何直接從ZipEntry(RubyZip,Paperclip,Rails 3)獲取臨時File對象(正確的內容類型,無需寫入磁盤)?

這裏是我的代碼:

def extract (file = nil) 
    Zip::ZipFile.open(file) { |zip_file| 
    zip_file.each { |image| 
     photo = self.photos.build 
     # photo.image = image # this doesn't work 
     # photo.image = File.open image # also doesn't work 
     # photo.image = File.new image.filename 
     photo.save 
    } 
    } 
end 

但問題是,photo.image是連接(通過回形針)的模型,並指定一些作爲附件需要的東西是一個文件對象。然而,我不能爲我的生活弄清楚如何將ZipEntry轉換爲文件。我所見過的打開或創建文件的唯一方法是在其路徑中使用字符串 - 這意味着我必須將文件提取到某個位置。真的,那似乎很愚蠢。爲什麼我不能將ZipEntry文件提取到輸出流並將其轉換爲文件?

所以最終的問題是:我可以從Zip文件中提取一個ZipEntry並將其直接轉換爲File對象(或直接將其作爲Paperclip對象附加)?或者,我堅持實際存儲在硬盤上,然後我可以附加它,即使該版本最終會被刪除?

UPDATE 感謝藍莓領域,我想我更接近我的解決方案。下面是我添加的代碼行,它給了我將它視爲/文件,我需要:

photo.image = zip_file.get_output_stream image 

但是,我Photo對象將不接受是越來越傳遞的文件,因爲它不是一個image/jpeg。實際上,檢查文件content_type顯示application/x-empty。我認爲這可能是因爲獲取輸出流似乎在文件的末尾附加了一個時間戳,因此最終看起來像imagename.jpg20110203-20203-hukq0n編輯:另外,它創建的臨時文件不包含任何數據並且大小爲0.所以看起來這可能不是答案。

所以,下一個問題:有誰知道如何得到這個給我一個圖像/ jpeg文件?

UPDATE

我一直是這樣一些玩耍。看起來輸出流不是要走的路,而是輸入流(這總是讓我感到困惑)。在ZipEntry上使用get_input_stream,我得到文件中的二進制數據。我想現在我只需要弄清楚如何將它放入Paperclip附件(作爲File對象)。我已經嘗試將ZipInputStream直接推送到附件,但當然,這是行不通的。我真的很難相信沒有人試圖將提取的ZipEntry作爲文件。有沒有理由認爲這會被認爲是糟糕的編程習慣?在我看來,像跳過磁盤寫臨時文件將是完全可以接受的,並支持像Zip歸檔管理。

無論如何,問題依然存在:

是否有輸入流轉換爲File對象(或臨時文件)的方法嗎?最好不必寫入磁盤。

回答

1

查看ZipFile上的get_input_stream和get_output_stream消息。

+0

我嘗試了這一點。使用zip_file.get_output_stream(image)確實產生了一個文件。但是,該模型似乎將該文件解釋爲「application/x-empty」,導致該文件失敗。它似乎還在讀取文件名'image_name.jpg20110203-20203-1lyjn3i',我認爲這是回形針給它的圖像進行版本跟蹤的標準時間戳。你知道一種方法來確保它被讀爲jpeg嗎? – 2011-02-04 02:57:35

+1

其實我只是查了一下。輸出流作爲Tempfile打開。該Tempfile創建時添加該時間戳。我只是檢查了提取的Tempfile的content_type,並將其作爲application/x-empty出現。 – 2011-02-04 03:19:07

6

試試這個

Zip::ZipFile.open(params[:avatar].path) do |zipfile| 
    zipfile.each do |entry| 
    filename = entry.name 
    basename = File.basename(filename) 

    tempfile = Tempfile.new(basename) 
    tempfile.binmode 
    tempfile.write entry.get_input_stream.read 

    user = User.new 
    user.avatar = { 
     :tempfile => tempfile, 
     :filename => filename 
    } 
    user.save 

    end 
end 
相關問題