【问题标题】:How do I save base64 image from html5 canvas as ImageField in Django?如何将 html5 画布中的 base64 图像保存为 Django 中的 ImageField?
【发布时间】:2019-09-17 18:21:03
【问题描述】:

在我的表单上,我有一个 ImageField 和一个隐藏的 CharField 来接受作为 base64 的图像。当用户在前端表单上选择图像时,我在前端的 JS 脚本会自动将图像大小调整为画布,然后将生成的 dataUrl 设置为 CharField 的内容。我希望在提交表单时,我可以将 base64 文本转换为图像并覆盖 ImageField 中原始图像的保存,以便将解码后的 base64 图像保存在其位置(文件名和所有)。

我遵循了几个在线教程,这些教程帮助我制定了以下代码。我已经覆盖了forms.py 中的clean() 函数,以便将base64 文本解码为PIL 图像。现在我想将其设置为实际 ImageField 的内容,以便将其保存和处理,就好像 base64 解码的图像是在 POST 中发送的文件一样。

其他答案建议使用 with open() 命令手动保存解码的 base64 图像,但这种方法会带来其他麻烦。特别是因为如果使用已经存在的名称提交图像,Django 已经处理图像重命名。我宁愿不必为此重新制造轮子。在通过 Django 的内置方法保存之前用生成的文件替换 ImageField 文件似乎是最好的方法。

我想要的方法有什么可行的方法吗?我没有找到任何试图处理这种情况的答案,而无需自己手动保存文件并在之后更新模型。

from PIL import Image
from io import BytesIO

import os
import sys
import re
import base64


    def clean(self):
        cleaned_data = super().clean()

        dataUrlPattern = re.compile('data:image/(png|jpeg);base64,(.*)$')
        ImageData = cleaned_data.get("image_base64_text")
        ImageData = dataUrlPattern.match(ImageData).group(2)
        ogImg = cleaned_data.get("image")

        # If none or len 0, means illegal image data
        if (ImageData == None or len(ImageData) == 0):
            # PRINT ERROR MESSAGE HERE
            print('corrupt or illegal image data')

        # Decode the 64 bit string into 32 bit
        ImageData = base64.b64decode(ImageData)
        ImageData = Image.open(BytesIO(ImageData))

【问题讨论】:

    标签: javascript python django html5-canvas


    【解决方案1】:

    在 form 中定义 clean_image 方法,并从 clean 方法中返回一个 InMemoryUploadedFile 的实例。 Ps 我鼓励你使用pep8 style guidelines 来进行变量命名和其他与代码风格相关的事情。

    def clean_image(self):
        dataUrlPattern = re.compile('data:image/(png|jpeg);base64,(.*)$')
        ImageData = self.cleaned_data.get("image_base64_text")
        ImageData = dataUrlPattern.match(ImageData).group(2)
    
        # If none or len 0, means illegal image data
        if (ImageData == None or len(ImageData) == 0):
            # PRINT ERROR MESSAGE HERE
            print('corrupt or illegal image data')
    
        # Decode the 64 bit string into 32 bit
        ImageData = base64.b64decode(ImageData)
        ImageData = Image.open(BytesIO(ImageData))
    
    
        return InMemoryUploadedFile(ImageData,
                                'ImageField', 'filename'),
                                'image/jpeg',
                                sys.getsizeof(output),
                                None)
    

    【讨论】:

    • 谢谢!我今晚会试试这个,看看它是如何工作的。我注意到您使用filename 作为InMemoryUploadedFile 名称的名称。如何使用cleaned_data.get("image")非base64 ImageField中使用的原始文件名?
    • 更新:我已经尝试过您的解决方案,但似乎 self.cleaned_data.get("image_base64_text") 返回 None。但是,self.cleaned_data.get("image") 确实返回了一个 InMemoryUploadedFile 对象。可能是我在clean_image() 内无法访问image_base64_text
    • 更新 2:我已将代码移至 clean() 方法,并手动编辑并返回其中的 self.cleaned_data 字典,以便将图像设置为您的返回值。但是现在form.save() 抱怨:'JpegImageFile' 对象没有属性'read'
    猜你喜欢
    • 2015-01-10
    • 1970-01-01
    • 2017-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多