Django从ImageField下载镜像

gzszwxb4  于 2023-03-31  发布在  Go
关注(0)|答案(7)|浏览(148)

我正在使用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? )

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

rdlzhqv9

rdlzhqv91#

你可以试试这段代码,也许需要一些注意事项:

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,用于获取倒数第二行...filename=%s" % img.name中的文件名。
1.在***ImageField***中有一个字段是file,在这里的代码中,我使用img.file来获取文件的路径,您应该为img.YOUR_IMAGE_FIELD.file或任何需要获取图像路径的内容更改该字段

qyuhtwio

qyuhtwio3#

一个基于类的views-type的例子是这样的(我使用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应该没有什么不同

pexxcrt2

pexxcrt24#

其他两个答案是可以的,但正如许多地方所宣传的那样,出于性能原因,不建议使用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。

vs91vp4v

vs91vp4v5#

这段代码在新版本的Django中运行良好:

import mimetypes

def download_image(request, id):
    img = ImageModel.objects.get(id=id)
    wrapper = img.field_name
    content_type = mimetypes.guess_type(img.field_name.name)[0]
    response = HttpResponse(wrapper, content_type=content_type)
    response['Content-Length'] = img.field_name.size
    response['Content-Disposition'] = f"attachment; filename={img.field_name.name}"
    return response

将field_name更改为字段。字段必须是ImageField或FileField。

ibrsph3r

ibrsph3r6#

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

# 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)
y3bcpkx1

y3bcpkx17#

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

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图像查看器会显示“Not a JPEG file. starts with 0x89 0x50”

相关问题