2014-10-26 78 views
1

我正在使用Django 1.7和Python 3.4。Django從ImageField下載圖像

我有這樣一個模型:

class ImageModel(models.Model): 
    image = models.ImageField(verbose_name='image', upload_to='uploaded_images/') 

現在我要下載的文件保存在/靜態/ uploaded_images /圖像。 例如我有這樣的鏈接:www.example.com/image/download/1,其中1是ImageModel對象的id。

現在我有一個觀點:

def download_image(request, image_id): 
    img = ImageModel.objects.get(id=image_id) 
    (what I need to do?) 

下一步是什麼?如何創建一個強制下載該圖像的視圖?

回答

3

你可以試試這個代碼,也許需要一些注意事項:

from django.core.servers.basehttp import FileWrapper 
import mimetypes 

def download_image(request, image_id): 
    img = ImageModel.objects.get(id=image_id) 
    wrapper  = FileWrapper(open(img.file)) # img.file returns full path to the image 
    content_type = mimetypes.guess_type(filename)[0] # Use mimetypes to get file type 
    response  = HttpResponse(wrapper,content_type=content_type) 
    response['Content-Length']  = os.path.getsize(img.file)  
    response['Content-Disposition'] = "attachment; filename=%s" % img.name 
    return response 
  1. 我假設有一個在您ImageModel.name在第二TO-獲取文件名最後一行...filename=%s" % img.name您應該編輯代碼以適合您的項目。

  2. 有在ImageField的現場file,在代碼在這裏我使用img.file獲得文件的路徑,你應該改變,對img.YOUR_IMAGE_FIELD.file或任何你需要獲得路徑圖像

+0

請注意,如果名稱在ASCII範圍內,但使用寬字符失敗時會失敗。 Content-Disposition支持UTF-8編碼名稱,但舊版瀏覽器(IE8之前)將完全忽略它。在內部,它更好地隱藏重定向到URL中具有文件名的URL。所有的瀏覽器都會支持這一點,你將避免IE瀏覽器附加的錯誤[1]錯誤,以避免出現文件名錯誤 – 2014-10-26 20:49:23

+0

@MikeMcMahon我不完全確定你想要解釋什麼,但我很樂意學習任何其他方式來做到這一點,如果它更好。你能給一些關於這方面的信息的鏈接嗎? – AlvaroAV 2014-10-26 20:51:02

+0

考慮使用漢字字符或西里爾文字符的文件名。 'filename =%s'將不起作用。它可以在FireFox/Chrome中使用,但不能在IE8以及可能的移動瀏覽器上使用(取決於使用哪種移動設備和瀏覽器技術)。有一個'filename * = UTF-8''%s'格式,它支持UTF-8編碼的字符,這有時會*有效*。最好(從DJango內部)執行HttpRedirect()到包含完整文件名的URL作爲路徑的一部分。所有的瀏覽器都可以解釋這個和標準範圍之外的字符。 – 2014-10-26 20:54:32

0

您需要使用Content-Disposition頭,看看這裏:

Generating file to download with Django
Django Serving a Download File

+1

雖然此鏈接可能回答此問題,但最好在此處包含答案的重要部分並提供供參考的鏈接。如果鏈接頁面更改,則僅鏈接答案可能會失效。 – 2014-10-26 21:50:42

+0

注意到,經驗教訓:) – 2014-10-27 14:06:41

0

其他兩個答案都可以,但是由於性能方面的原因,不推薦使用Django提供靜態文件的許多地方進行廣告宣傳。最好使用你的web服務器(nginx/apache ...)來提供服務。

您不需要額外的視圖來提供靜態文件。簡單地呈現在你的模板文件鏈接:

<a href="{{object.image.url}} download">Download this image!</a> 

objectImageModel一個實例。

django.db.models.fields.files.FieldFile.url

如果你真的想擁有像www.example.com/image/download/1可以簡單的寫重定向從現場獲得的圖像URL上的視圖的URL的視圖。

+0

這將打開webbrowser中的圖像,我想要的是強制將此圖像下載到用戶下載文件夾;)。 – 2014-10-26 21:20:02

+0

我編輯答案添加http://www.w3schools.com/tags/att_a_download.asp – dukebody 2014-10-26 22:33:10

-1

這裏是包含任何字符類型

# Even better as it works in any browser (mobile and desktop) 
def safe_name(file_name): 
    """ 
    Generates a safe file name, even those containing characters like ? and & 
    And your Kanji and Cyrillics are supported! 
    """ 
    u_file_name = file_name.encode('utf-8') 
    s_file_name = re.sub('[\x00-\xFF]', lambda c: '%%%02x' % ord(c.group(0)), u_file_name) 
    return s_file_name 

# Handled by url(r'^/image/download/(\d+)/.+$ 
def safe_download_image(request, image_id): 
    """ 
    Safely downloads the file because the filename is part of the URL 
    """ 
    img = ImageModel.objects.get(id=image_id) 
    wrapper  = FileWrapper(open(img.file)) # img.file returns full path to the image 
    content_type = mimetypes.guess_type(filename)[0] # Use mimetypes to get file type 
    response  = HttpResponse(wrapper,content_type=content_type) 
    response['Content-Length']  = os.path.getsize(img.file)  
    # This works for most browsers, but IE will complain sometimes 
    response['Content-Disposition'] = "attachment;" 
    return response 

def download_image(request, image_id): 
    img = ImageModel.objects.get(id=image_id) 
    redirect_do = safe_name(img.name) 
    return HttpResponseRedirect('/image/download/' + img_id + '/' + redirect_to) 
+0

不幸的是它是行不通的。請參閱下面的答案。 – 2014-10-26 21:55:21

+0

我從我用於我們的文件分發系統的源代碼中提取這個。什麼沒有用? – 2014-10-26 22:05:51

+0

@SzymonBarylak什麼不適合你? – 2014-10-27 00:39:50

-1

它不工作的文件你跨瀏覽器的安全下載。我做了這樣的事情:

wrapper = FileWrapper(img.file) # img.file returns full path to the image 
content_type = mimetypes.guess_type(str(img.file))[0] # Use mimetypes to get file type 
response = HttpResponse(wrapper, content_type=content_type) 
response['Content-Length'] = os.path.getsize(str(img.file)) 
response['Content-Disposition'] = "attachment; filename=%s" % img.name 

其中img點我ImageField領域。文件已下載,但無法打開。xUbuntu圖像查看器seys'不是JPEG文件。用0x89上爲0x50' 開始

+0

ANY JPEG文件的前兩個字節應分別爲0xFF和0xE0。上傳或下載時,您是否在任何時候不將圖像視爲二進制文件?任何影響內容的操作都應該分別以'rb'或'wb'模式打開文件。 – 2014-10-27 21:36:37

0

這方面的一個類爲本次型exampe會是這樣(我使用python魔法才能得到正確的內容類型的文件):

import os 
import magic 

from django.views.generic import View 
from django.http import HttpResponse 

from .models import ImageModel 


class ImageDownloadView(View): 

    def get(self, request, *args, **kwargs): 
     image = ImageModel.objects.get(pk=self.kwargs['image_id']) 
     image_buffer = open(image.file.path, "rb").read() 
     content_type = magic.from_buffer(image_buffer, mime=True) 
     response = HttpResponse(image_buffer, content_type=content_type); 
     response['Content-Disposition'] = 'attachment; filename="%s"' % os.path.basename(image.file.path) 
     return response 

這適用於Django 1.10.7,但不應該與Django 1.7不同1.2