Django从ImageField下载图像

时间:2014-10-26 20:27:04

标签: python django

我正在使用Django 1.7和Python 3.4。

我有一个像这样的模型:

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

现在我要下载保存在/ static / 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? )

下一步是什么?如何创建一个强制下载该图像的视图?

6 个答案:

答案 0 :(得分: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. 我假设您的.name中有一个字段ImageModel,以便在倒数第二行...filename=%s" % img.name中获取该文件的名称您应该编辑代码以适合您的项目。

  2. ImageField 中的字段为file,在此处的代码中我使用img.file来获取路径对于文件,您应该更改img.YOUR_IMAGE_FIELD.file或获取图像路径所需的任何内容

答案 1 :(得分:1)

您需要使用Content-Disposition标题,请点击此处:

Generating file to download with Django
Django Serving a Download File

答案 2 :(得分: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这样的网址中拥有一个视图,你只需编写一个重定向到从该字段获取的图像网址的视图。

答案 3 :(得分:0)

基于类的视图类型示例就像这样(我使用python-magic来获取文件的正确内容类型):

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不同

答案 4 :(得分:-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)

答案 5 :(得分:-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 image viewer seys'不是JPEG文件。以0x89 0x50'

开头