将解码的临时图像保存到 Django Imagefield
Posted
技术标签:
【中文标题】将解码的临时图像保存到 Django Imagefield【英文标题】:Saving a decoded temporary image to Django Imagefield 【发布时间】:2013-02-13 11:23:51 【问题描述】:我正在尝试将作为 Base64 编码文本传递给我的图像保存到 Django Imagefield 中。
但它似乎没有正确保存。数据库报告我所有的图像都存储为“”,当它应该将它们报告为文件名时,例如:
"template_images/template_folders/myImage.png"
试图保存我的图像的代码如下:
elif model_field.get_internal_type() == "ImageField" or model_field.get_internal_type() == "FileField": # Convert files from base64 back to a file.
if field_elt.text is not None:
setattr(instance, model_field.name, File(b64decode(field_elt.text)))
【问题讨论】:
【参考方案1】:基于此 SO 答案的另一种好方法:https://***.com/a/28036805/6143656 尝试并在 django 1.10 中进行了测试
我为解码的base64文件做了一个函数。
def decode_base64_file(data):
def get_file_extension(file_name, decoded_file):
import imghdr
extension = imghdr.what(file_name, decoded_file)
extension = "jpg" if extension == "jpeg" else extension
return extension
from django.core.files.base import ContentFile
import base64
import six
import uuid
# Check if this is a base64 string
if isinstance(data, six.string_types):
# Check if the base64 string is in the "data:" format
if 'data:' in data and ';base64,' in data:
# Break out the header from the base64 content
header, data = data.split(';base64,')
# Try to decode the file. Return validation error if it fails.
try:
decoded_file = base64.b64decode(data)
except TypeError:
TypeError('invalid_image')
# Generate file name:
file_name = str(uuid.uuid4())[:12] # 12 characters are more than enough.
# Get the file name extension:
file_extension = get_file_extension(file_name, decoded_file)
complete_file_name = "%s.%s" % (file_name, file_extension, )
return ContentFile(decoded_file, name=complete_file_name)
然后就可以调用函数了
import decode_base64_file
p = Post(content='My Picture', image=decode_based64_file(your_base64_file))
p.save()
【讨论】:
【参考方案2】:我想这是最干净和最短的方法。
这是在基于 Django(也称为 drf)的 API 端的发布请求中处理 Base64 编码图像文件的方法,该 API 将其保存为 ImageField。
假设你有一个模型如下:
Class MyImageModel(models.Model):
image = models.ImageField(upload_to = 'geo_entity_pic')
data=model.CharField()
所以对应的序列化器如下:
from drf_extra_fields.fields import Base64ImageField
Class MyImageModelSerializer(serializers.ModelSerializers):
image=Base64ImageField()
class meta:
model=MyImageModel
fields= ('data','image')
def create(self, validated_data):
image=validated_data.pop('image')
data=validated_data.pop('data')
return MyImageModel.objects.create(data=data,image=image)
对应的View可以如下:
elif request.method == 'POST':
serializer = MyImageModelSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=201)
return Response(serializer.errors, status=400)
注意在序列化器中我使用了模块django-extra-field中提供的Base64ImageField实现
要安装这个模块,运行命令
pip install pip install django-extra-fields
导入相同并完成!
将您的图像作为 JSON 对象中的 Base64 编码字符串连同您拥有的任何其他数据一起发送(通过 post 方法)。
【讨论】:
【参考方案3】:阅读this answer 后,我得到了这个工作:
from base64 import b64decode
from django.core.files.base import ContentFile
image_data = b64decode(b64_text)
my_model_instance.cool_image_field = ContentFile(image_data, 'whatup.png')
my_model_instance.save()
因此,我建议您将代码更改为:
from django.core.files.base import ContentFile
# Your other code...
elif model_field.get_internal_type() == "ImageField" or model_field.get_internal_type() == "FileField": # Convert files from base64 back to a file.
if field_elt.text is not None:
image_data = b64decode(field_elt.text)
setattr(instance, model_field.name, ContentFile(image_data, 'myImage.png'))
然后,假设您的ImageField
是使用设置为template_images/template_folders/
的upload_to
参数定义的,您应该会看到文件保存到YOUR_MEDIA_URL/template_images/template_folders/myImage.png
【讨论】:
我尝试采用相同的方法,但在解码时得到“不正确的填充”。有什么建议吗? 是的,你不想包含初始数据:image/gif;base64, bit 但是我想你现在可能已经知道了,只是为了像我这样通过谷歌来到这里的人做了。 我认为这个可能会失败,因为您不需要包含data:image/*;base64,
文件的一部分。以上是关于将解码的临时图像保存到 Django Imagefield的主要内容,如果未能解决你的问题,请参考以下文章