You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在表单中使用canvas实现用户绘图保存并关联存储至数据库

问题排查与修复方案

现有实现的核心问题

  • 表单嵌套违规:你在主表单formWithElectroSignature内部嵌套了隐藏表单signatureform,HTML规范禁止表单嵌套,会导致提交时数据丢失、提交目标错误
  • 提交逻辑错误:JS点击保存时提交的是内层无业务字段的隐藏表单,而非包含人员、日期等字段的主表单,业务数据和签名完全没有一起传递到后端
  • 无用代码干扰:window.location.assign=img、img.download = 'image.png'属于无效代码,前者会尝试跳转页面打断提交,后者对base64字符串设置属性毫无作用
  • 画布清空逻辑错误:重置按钮调用clearRect时用了窗口宽高作为参数,无法完全清空自定义尺寸的画布
  • 前端资源引入错误:jQuery的script标签没有闭合,会导致后续JS加载执行失败

修复步骤

1. 修正Twig表单结构

删掉嵌套的隐藏表单,将签名隐藏字段移到主表单内,闭合script标签:

{% extends '@!EasyAdmin/layout.html.twig' %}

{% block content %}

{% for flashError in app.flashes('verify_email_error') %}
    <div class="alert alert-danger" role="alert">{{ flashError }}</div>
{% endfor %}

{{ form_start(formWithElectroSignature) }}
    <!-- 签名隐藏字段移到主表单内 -->
    <input type="hidden" id="signature" name="signature">
    <div class="form-control js-user-autocomplete" autocomplete="on">
        {{ form_label(formWithElectroSignature.personnel) }}<br>
        {{ form_widget(formWithElectroSignature.personnel) }}
    </div>
    <div class="form-control">
        <i class="fa fa-calendar"></i> {{ form_label(formWithElectroSignature.dateDebut) }}<br>
        {{ form_widget(formWithElectroSignature.dateDebut) }}
    </div>
    <div class="form-control">
        {{ form_label(formWithElectroSignature.cle) }}<br>
        {{ form_widget(formWithElectroSignature.cle) }}
    </div>
    <div class="form-control">
        {{ form_label(formWithElectroSignature.document) }}<br>
        {{ form_widget(formWithElectroSignature.document) }}
    </div>
    <div class="form-control">
        <div class="col-md-8 col-md-offset-2">
            <br>
            <h2>Signature Electronique !</h2>
            <hr>
            <div id="canvasDiv"></div>
            <br>
            <button type="button" class="btn btn-danger" id="reset-btn">Clear</button>
            <button type="button" class="btn btn-success" id="btn-save">Save</button>
        </div>
    </div>
{{ form_end(formWithElectroSignature) }}

{% endblock %}

{% block body_javascript %}
<!-- 闭合script标签 -->
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha256-pasqAKBDmFT4eHoN2ndd6lN370kFiGUFyTiUHWhU7k8=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.5.0-beta4/html2canvas.min.js"></script>
<script src="/signatures/Signature.js"></script>
{% endblock %}

2. 修正JS逻辑

修改保存和清空逻辑,移除无效代码:

// 修改reset-btn点击事件
$("#reset-btn").click(function() {
    // 用canvas自身宽高清空
    context.clearRect(0, 0, canvas.width, canvas.height);
    clickX = [];
    clickY = [];
    clickDrag = [];
});

// 修改btn-save点击事件
$(document).on('click', '#btn-save', function() {
    var mycanvas = document.getElementById('canvas');
    // 指定png格式保证兼容性
    var imgBase64 = mycanvas.toDataURL("image/png");
    // 把base64赋值给主表单的隐藏字段
    $("#signature").val(imgBase64);
    // 直接提交主表单
    $("form[name=formWithElectroSignature]").submit();
});

3. 后端处理逻辑(Symfony框架示例)

后端接收base64字符串,转成png文件存储到服务器,再将文件名关联存入数据库:

// 控制器中接收提交数据
public function submitSignature(Request $request)
{
    $signatureBase64 = $request->request->get('signature');
    // 去掉base64头
    $base64Body = preg_replace('#^data:image/\w+;base64,#i', '', $signatureBase64);
    $fileContent = base64_decode($base64Body);
    // 生成唯一文件名
    $fileName = uniqid().'_signature.png';
    // 存储到指定目录
    file_put_contents($this->getParameter('signature_directory').'/'.$fileName, $fileContent);
    
    // 后续业务逻辑:将文件名和其他表单字段一起存入数据库
    $entity = new SignatureEntity();
    $entity->setPersonnel($request->request->get('personnel'));
    $entity->setSignaturePath($fileName);
    // 其他字段赋值...
    $em = $this->getDoctrine()->getManager();
    $em->persist($entity);
    $em->flush();
    
    return $this->redirectToRoute('success_page');
}

实现方向说明

你原本的实现思路是正确的,通过canvas收集手写内容、转base64提交是业内通用的手写签名实现方案,仅需修正上述细节问题即可正常运行。

内容的提问来源于stack exchange,提问作者Cephalopodius

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 05:15:03