首页 文章

Django从ImageField下载图像

提问于
浏览
1

我正在使用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 回答

  • 1

    您可以尝试此代码,可能需要一些注意事项:

    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
    
    • 我假设您的 ImageModel 中有一个字段 .name 来获取倒数第二行中的文件名 ...filename=%s" % img.name 您应该编辑代码以适合您的项目 .

    • ImageField 中有一个字段 file ,在这里的代码中我使用 img.file 获取文件的路径,您应该更改 img.YOUR_IMAGE_FIELD.file 或获取图像路径所需的任何内容

  • -1

    你需要使用 Content-Disposition Headers ,看看这里:

    Generating file to download with Django
    Django Serving a Download File

  • 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的视图 .

  • -1

    基于类的视图类型示例就像这样(我使用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不应该有所不同

  • 3

    这是您的跨浏览器安全下载包含任何字符类型的文件

    # 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

    它不起作用 . 我做了这样的事情:

    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 字段 . 文件已下载,但我可以't open it. xUbuntu image viewer seys '不是JPEG文件 . 以0x89 0x50'开头

相关问题