HTML5+jSignature插件手写签名生成图片并转换成文件流实现功能

公司需求html5手写签名,并转换成图片上传服务器

  • 项目结构:jquery+springboot项目需要引入js文件:jquery的jquery.min.js 、jSignature插件的 jSignature.min.js 、flashcanvas.js文件 小白注意:引入js的方式我是通过thymeleaf,不是该模板的请通过绝对路径或者相对路径等其他方式引入,其中ajax中的url路径已置空,自行添加。
    • 效果图如下
    • 前端HTML5部分代码
    • 后端接收数据部分代码

链接: jSignature官方插件下载地址,下载后解压找到lib文件导入到自己项目中去并引用即可.
项目结构:jquery+springboot项目需要引入js文件:jquery的jquery.min.js 、jSignature插件的 jSignature.min.js 、flashcanvas.js文件 小白注意:引入js的方式我是通过thymeleaf,不是该模板的请通过绝对路径或者相对路径等其他方式引入,其中ajax中的url路径已置空,自行添加。

关于为何不直接通过base64传输图片?公司xss拦截代码会拦截关键字,直接传输base64会被拦截,所有最终选择使用ajax传输流文件上传图片

**

效果图如下

**
在这里插入图片描述

前端HTML5部分代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<!DOCTYPE html>
<html xmlns:th="http://www.w3.org/1999/xhtml">
<meta charset="utf-8">
<meta name="context-path" th:content="@{/}"/>
<style type="text/css">
    a{text-decoration:none;}
    a:hover{ text-decoration:none;}
    #box{
        width: 100%;
        height: 400px;
        border: 1px solid #eaeaea;
    }
    canvas{
        height: 400px !important;
    }
    .abspan{
        color: #ffffff;
        display: block;
        width: 100px;
        font-size: 16px;
        text-align: center;
        line-height: 40px;
        background: dodgerblue;
        margin-bottom: 10px;
    }
</style>


<body>
<div style="margin: 12px;">
        <div class="form-group">
            <label class="col-sm-3 control-label">本人姓名确认</label>
            <div class="col-sm-8">
                <div id="box">

                </div>
                <span class="abspan" id="su">确认</span>
                <span class="abspan" id="re">重置</span>
                <img src="" alt="" id="image">
            </div>
        </div>
        <div class="form-group">
            <div class="col-sm-8 col-sm-offset-3">
                <a id="save" class="btn btn-primary" οnclick="javascript:save()">提交</a> &emsp;&emsp;&emsp;
            </div>
        </div>
    </form>

</div>
<script type="text/javascript"th:src="@{/js/jquery.min.js}"></script>
<script type="text/javascript"th:src="@{/js/jSignature.min.js}"></script>
<script type="text/javascript"th:src="@{/js/flashcanvas.js}"></script>
<script>
    $(function() {
        $("#box").jSignature();//初始化画板,初始化之后就可以进行操作
    });
    function save() {
        //先将图片保存到服务器,在把其他表单数据提交到服务器(具体如何关联取决业务)
        saveImage();
        saveForm();
    }
    //点击事件为获取base64数据,生成图片
    document.getElementById("su").onclick = function(){
        //getData:获取数据
        //reset:复位/重置
        // 获取签名的“base64”数据对
        var datapair = $("#box").jSignature("getData","image");
        //此处打印的是完整的base64转码,可以复制后去在线转码测试一下是否正常
        console.log('data:' + datapair[0] + "," + datapair[1])
        //将图片展示出来
        $("#image").attr('src','data:' + datapair[0] + "," + datapair[1]);
    }
    //生成图片之后我们就可以进行相应的操作

    //点击事件为重置画板
    document.getElementById("re").onclick = function(){
        $("#box").jSignature("reset");
        $("#image").attr('src','');
    }
    var url='';//设置你们的url
    //保存整个表单在此之前已经将图片上传到服务器了
    function saveForm(){
        $.ajax({
            cache : true,
            type : "POST",
            url : url,
            data : $('#form').serialize(), // 你的formid
            async : false,
            error : function(request) {
               alert("网络超时");
            },
            success : function(data) {
                console.log(data)
            }
        });
    }
    //重点来了,该方法将Base64格式转换成流格式
    function  base64toFile(dataurl, filename) {
        let arr = dataurl.split(',')
        let mime = arr[0].match(/:(.*?);/)[1]
        let suffix = mime.split('/')[1]
        let bstr = atob(arr[1])
        let n = bstr.length
        let u8arr = new Uint8Array(n)
        while (n--) {
            u8arr[n] = bstr.charCodeAt(n)
        }
        return new File([u8arr], `${filename}.${suffix}`, {
            type: mime
        })
    }
    function saveImage() {
        var url='';//设置你们的url
        var datapair = $("#box").jSignature("getData","image");  //将canvas里面的数据转换成base64数组
        var imgBase64='data:' + datapair[0] + "," + datapair[1];  //封装成正确的base64
        var file= base64toFile(imgBase64,'file');     //base64转换成流文件,可以打印出来看下
        let formData = new FormData()            //封装成formData格式
        formData.append('type', 97);
        formData.append('file', file)
        $.ajax({
            contentType: false,   //不可少
            processData: false,   //不可少
            type : "POST",
            url : url,
            data : formData,
            async : false,
            error : function(request) {
                alert("网络超时");
            },
            success : function(data) {
               console.log(data)
            }
        });
    }
</script>
</body>
</html>

后端接收数据部分代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//上传文件并通过流的方式接收,我的业务做法是将文件上传后拿到文件id及地址存储到数据库,
//拿到流文件后如何上传具体可以参考别的文章
    @PostMapping("/upLoadItemImage")
    @ResponseBody
    public String upLoadItemImage(HttpServletRequest request, Integer  type) {
        MultipartHttpServletRequest fileRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = fileRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();
            int id = 0;

            try {
                InputStream inputStream = file.getInputStream();
                //自行操作
                //...
            } catch (Exception e) {
                e.printStackTrace();
            }
            if(id == 0){
                return "error" ;
            }
        }

        return  "ok";
    }