Django 从 ImageField 下载图片
我正在使用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? )
接下来该怎么做?如何创建一个视图来强制下载那张图片呢?
7 个回答
这段代码在新版本的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(文件字段)。
其他两个回答都不错,但很多地方都提到,使用Django来提供静态文件并不是一个好主意,主要是因为性能问题。更好的做法是通过你的网页服务器(比如nginx或apache)来提供这些文件。
你不需要额外的视图来提供静态文件。只需在你的模板中渲染一个指向文件的链接就可以了:
<a href="{{object.image.url}} download">Download this image!</a>
这里的 object
是 ImageModel
的一个实例。
你可以查看 django.db.models.fields.files.FieldFile.url 来获取更多信息。
如果你真的想要一个像 www.example.com/image/download/1
这样的URL,你可以简单地写一个视图,来重定向到从字段获取的图片URL。
一个基于类视图的例子可以是这样的(我使用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中应该也差不多。
你需要使用 Content-Disposition
这个头部信息,看看这里:
你可以试试这个代码,不过可能需要注意一些细节:
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
,或者根据你的需要来获取图片的路径。