2011-02-27 360 views
24

所以這應該很容易,但我不能得到它的工作。渲染圖像

我有一個控制器方法,查找基於查詢的圖像,然後輸出緩存。圖像可能是遙遠的(flickr,谷歌圖片等),或者它可能是本地的。無論來源如何,我只需要拍攝圖像文件內容,並將其傳遞給用戶。本質上來說,一個代理。通過遠程圖像似乎工作正常,但通過本地圖像給我:

invalid byte sequence in UTF-8 

所以這就是我得到的。我希望有人能夠解決這個問題,或者用我的代碼指導我更好的方向。

def image_proxy 
    query = params[:query] 
    image_url = get_image_url(query) # returns an absolute local file path or a URL 

    response.headers['Cache-Control'] = "public, max-age=#{12.hours.to_i}" 
    response.headers['Content-Type'] = 'image/jpeg' 
    response.headers['Content-Disposition'] = 'inline' 
    render :text => open(image_url).read 
end 

遠程文件正常工作,本地文件沒有。

獎勵給任何人,可以幫助解決這個問題,其他:

  1. 我需要設置正確的內容類型。遠程圖像網址不告訴我圖像類型,我只是得到一個網址,有時URL不包含擴展名。所以我選擇了jpeg,因爲無論發送給我的圖像類型如何,它都可以工作。

謝謝!

回答

23

嘗試使用render :text => open(image_url, "rb").read,它告訴Ruby它打開的文件是二進制文件,而不是嘗試將其作爲文本讀取。

編輯

對於獎金問題,你可以閱讀的前幾個字節,看看它們包含的內容。 PNG將始終以十六進制字節值89 50 4E 47 0D 0A 1A 0A(或十進制值137 80 78 71 13 10 26 10)開頭。

維基百科有一個list of magic numbers used to identify file,你可以看看。只需創建一些讀取前幾個字節的方法並將其與之進行比較即可。

+0

很好的答案,完美的工作。 –

14

什麼版本的Rails?對於Rails 3,您應該查看已添加的streaming methods。 send_data將是發送二進制數據的正確方式。如果圖像是本地的,並且您的Web服務器支持它,則可以使用send_file,在用戶下載圖像時不會阻止rails實例。

+1

是的,'send_data'是你想要的,而不是'render'。 – aceofspades