【问题标题】:How to bind base64 data in a django form ImageField如何在 django 表单 ImageField 中绑定 base64 数据
【发布时间】:2016-06-05 12:46:33
【问题描述】:

我正在实现一个 ajax 表单提交,它会在提交图像之前调整图像大小。 javascript 基本上将文件读取为Image,调整大小并绘制到canvas,然后将数据附加到FormData 对象:

var fd = new FormData();
fd.append("image0", canvas.toDataURL("image/png"));

然后我将 ajax 提交到我的 django 视图,并使用 ModelForm 进行验证:

forms.py

class InsertProduct(forms.ModelForm):
    image0 = forms.ImageField(
        required=True, 
        max_length=64, 
        widget=forms.FileInput( attrs={"id": "image0",} )
    )

views.py

def ajax_upload(request):
    if request.method == 'POST':
        form = InsertProduct(request.POST, request.FILES)
        print(request.POST.urlencode())
        print(form.errors)

urlencode() 告诉我我正在接收数据:

image0=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAABE...

但是表单错误告诉我我没有正确绑定它:

<ul class="errorlist">
    <li>image0<ul class="errorlist"><li>This field is required.</li></ul></li>
</ul>

也许 ImageField 是在 request.FILES 而不是 request.POST 中寻找数据?我如何让它工作?

【问题讨论】:

  • 是的,它会在 request.FILES 中查找它,你为什么不那样发送它? Base64 编码和上传是一种浪费。广告大约占数据包大小的 30%。
  • 这是一个简化的例子——真实的应用程序有多个图像。我试图减轻的风险是有人上传了 10-20Mb 的图像,这些图像需要调整到 400-500kb 的服务器端。在浏览器中调整大小(在用户完成表单时并行)比在服务器上要快得多。 (我也没有为服务器带宽付费,但我为 CPU 内核付费)。是否可以在javascript中将数据绑定到request.FILES,或者从request.POST获取ImageField
  • 你看过blueimp jquery 上传。似乎符合您的要求。

标签: javascript ajax django forms


【解决方案1】:

所以简短的回答是使用像pillow这样的图像库将base64转换回Image文件,然后手动保存。

但是,如果你可以依赖浏览器的FormData API,你可以这样做:

var fd = new FormData(document.forms[0]);
var quality = 0.95;
canvas.toBlob(function(blob){
    fd.set("image0", blob, "myimage.jpg");
}, "image/jpeg", quality);

请注意,Chrome 仅支持来自最新稳定版本 50 的 FormData setappend,当我尝试 set blob 时,我的构建会引发异常。似乎 Firefox 46 会做到这一点(我认为从 44 开始支持 setappend),但前提是 FormData() 是从 DOM &lt;form&gt; 元素初始化的。如果您检查 POST,您会发现文件输入字段(在 DOM 中不存在并在其后附加)丢失。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-26
  • 2011-05-14
  • 2014-11-26
  • 1970-01-01
  • 2022-06-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多