我有Apache2 + PIL + Django + X-sendfile。我的问题是,当我保存动画GIF时,当我通过浏览器输出时,它不会“动画”。
这是我的代码,用于显示位于公共可访问目录之外的图像。
def raw(request,uuid):
target = str(uuid).split('.')[:-1][0]
image = Uploads.objects.get(uuid=target)
path = image.path
filepath = os.path.join(path,"%s.%s" % (image.uuid,image.ext))
response = HttpResponse(mimetype=mimetypes.guess_type(filepath))
response['Content-Disposition']='filename="%s"'\
%smart_str(image.filename)
response["X-Sendfile"] = filepath
response['Content-length'] = os.stat(filepath).st_size
return response
更新
事实证明它有效。我的问题是当我尝试通过URL上传图像时。它可能无法保存整个GIF?
def handle_url_file(request):
"""
Open a file from a URL.
Split the file to get the filename and extension.
Generate a random uuid using rand1()
Then save the file.
Return the UUID when successful.
"""
try:
file = urllib.urlopen(request.POST['url'])
randname = rand1(settings.RANDOM_ID_LENGTH)
newfilename = request.POST['url'].split('/')[-1]
ext = str(newfilename.split('.')[-1]).lower()
im = cStringIO.StringIO(file.read()) # constructs a StringIO holding the image
img = Image.open(im)
filehash = checkhash(im)
image = Uploads.objects.get(filehash=filehash)
uuid = image.uuid
return "%s" % (uuid)
except Uploads.DoesNotExist:
img.save(os.path.join(settings.UPLOAD_DIRECTORY,(("%s.%s")%(randname,ext))))
del img
filesize = os.stat(os.path.join(settings.UPLOAD_DIRECTORY,(("%s.%s")%(randname,ext)))).st_size
upload = Uploads(
ip = request.META['REMOTE_ADDR'],
filename = newfilename,
uuid = randname,
ext = ext,
path = settings.UPLOAD_DIRECTORY,
views = 1,
bandwidth = filesize,
source = request.POST['url'],
size = filesize,
filehash = filehash,
)
upload.save()
#return uuid
return "%s" % (upload.uuid)
except IOError, e:
raise e
有什么想法吗?
谢谢!
Wenbert
答案 0 :(得分:3)
Image
课程的来源和Image.open
的内容是什么?
我的猜测是它对图像数据进行了一些消毒(这是一件好事),但只保存了Gif的第一帧。
修改强>
我确信这是PIL的一个问题。 PIL documentation on GIF说:
PIL读取GIF87a和GIF89a版本的GIF文件格式。该库写入了行程编码的GIF87a文件。
要验证,您可以将im
的内容直接写入磁盘并与源图像进行比较。
答案 1 :(得分:1)
问题是保存PIL打开的图像版本。当你通过PIL保存它时,它只会保存第一帧。
然而,有一个简单的解决方法:制作文件的临时副本,使用PIL打开,然后如果您检测到它是动画GIF,则只保存原始文件,而不是PIL打开的版本。
如果您保存原始动画GIF文件,然后将其流回到您的HTTP响应中,它将通过动画显示在浏览器中。
用于检测您的PIL对象是否为动画GIF的示例代码:
def image_is_animated_gif(image):
# verify image format
if image.format.lower() != 'gif':
return False
# verify GIF is animated by attempting to seek beyond the initial frame
try:
image.seek(1)
except EOFError:
return False
else:
return True