Laravel表单实现签名手绘或上传二选一功能故障求解
问题解决步骤
1. 核心问题定位
- 表单默认不支持文件上传:上传文件需要给form标签添加
enctype="multipart/form-data"属性,否则文件参数不会被正常提交,甚至会影响其他普通字段的传输 - 控制器获取文件方法错误:Laravel中不能用
$request->input('file')获取上传文件,必须用$request->file('file')或者$request->hasFile('file')做判断 - 缺少二选一冲突处理:没有做两种签名方式的字段互斥处理,可能出现两个字段同时有值的异常情况
2. 代码修改方案
2.1 修改Blade表单代码
把form标签加上enctype属性,恢复上传输入框,补充跨站校验字段:
<form method="POST" action="{{ route('signaturepad.upload') }}" enctype="multipart/form-data"> @csrf <div class="tab-content"> <div class="tab-pane fade show active" id="draw"> <div class="col-md-12"> <label class="" for="">Draw Signature:</label> <br/> <div id="sig"></div> <br><br> <button id="clear" class="btn btn-danger">Clear Signature</button> <textarea id="signature" name="signature" style="display: none"></textarea> </div> </div> <div class="tab-pane fade" id="upload"> <label class="" for="">Upload Signature:</label> <div class="form-group"> <input type="file" name="file" id="file" accept="image/*"> </div> </div> <button class="btn btn-success" type="submit">Save</button> </div> </form>
2.2 修改Javascript代码
新增tab切换时的字段清空逻辑,实现两种方式互斥:
<script src="{{ asset('js/pages/jquery.signature.js')}}"></script> <script type="text/javascript"> var sig = $('#sig').signature({syncField: '#signature', syncFormat: 'PNG'}); $('#clear').click(function(e) { e.preventDefault(); sig.signature('clear'); $("#signature").val(''); }); // 新增tab切换互斥逻辑(适配Bootstrap tab事件,旧版Bootstrap可对应调整事件名) $('button[data-bs-toggle="tab"], a[data-bs-toggle="tab"]').on('shown.bs.tab', function (e) { const activeTab = $(e.target).attr("href"); if(activeTab === '#draw'){ // 切到手绘时清空上传文件 $('#file').val(''); }else if(activeTab === '#upload'){ // 切到上传时清空手绘签名 sig.signature('clear'); $("#signature").val(''); } }) </script>
2.3 修改Controller代码
用Laravel自带校验规则实现二选一必填,分别处理两种签名场景:
public function upload(Request $request) { // 自动校验两个字段二选一必填,同时校验上传文件为合法图片 $request->validate([ 'signature' => 'required_without:file', 'file' => 'required_without:signature|file|image|max:2048', ]); $folderPath = public_path('uploads/'); $fileName = uniqid().'.png'; if(!empty($request->input('signature'))){ // 处理手绘签名 $data_uri = $request->signature; $encoded_image = explode(",", $data_uri)[1]; $decoded_image = base64_decode($encoded_image); file_put_contents($folderPath.$fileName, $decoded_image); }elseif($request->hasFile('file')){ // 处理上传签名 $request->file('file')->move($folderPath, $fileName); } // 后续业务逻辑自行补充 return view('dashboard')->with('sign_path', 'uploads/'.$fileName); }
3. 效果验证
- 手绘场景:切到手绘tab签名后提交,可正常生成签名文件
- 上传场景:切到上传tab选择图片后提交,可正常保存上传的签名文件
- 两种方式不会互相干扰,同时为空会触发校验报错
内容的提问来源于stack exchange,提问作者patrick
相关产品推荐
相关产品推荐

