前端插件——头像截图上传插件的使用(带后台)

效果图:实现上传头像,右边是预览,有三个大小,可以对头像进行裁剪

HTML:

toParentData 和 img 返回的是图片裁剪后的base64编码。其中toParentData用于业务需求,可以忽略。
<!DOCTYPE html>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<c:set var="BASE" value="${pageContext.request.contextPath}"/>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%> 
    <meta charset="UTF-8">
   <title>头像编辑上传</title>
    <link rel="stylesheet" href="${BASE}/www/css/userinfo/headImg_style.css" type="text/css" />

    <!-- end -->
   <script>var BASE = "${BASE}";</script>    
    </head>
    
<body>
<script type="text/javascript" src="${BASE}/www/js/jquery/jquery-1.11.1.min.js"></script> 
<script type="text/javascript" src="${BASE}/www/js/userinfo/headImg_cropbox.js"></script>
<div class="container">
  <div class="imageBox">
    <div class="thumbBox"></div>
    <div class="spinner" style="display: none">Loading...</div>
  </div>
  <div class="action"> 
    <!-- <input type="file" id="file" style=" width: 200px">-->
    <div class="new-contentarea tc"> <a href="javascript:void(0)" class="upload-img">
      <label for="upload-file">上传图像</label>
      </a>
      <input type="file" class="" name="upload-file" id="upload-file" />
    </div>
    <input type="button" id="btnCrop"  class="Btnsty_peyton" value="裁切">
    <input type="button" id="btnZoomIn" class="Btnsty_peyton" value="+"  >
    <input type="button" id="btnZoomOut" class="Btnsty_peyton" value="-" >
  </div>
  <div class="cropped"></div>
</div>
<script type="text/javascript">
var toParentData ='';
$(window).load(function() {
    var options =
    {
        thumbBox: '.thumbBox',
        spinner: '.spinner',
        imgSrc: ''
    }
    var cropper = $('.imageBox').cropbox(options);
    $('#upload-file').on('change', function(){
        var reader = new FileReader();
        reader.onload = function(e) {
            options.imgSrc = e.target.result;
            cropper = $('.imageBox').cropbox(options);
        }
        reader.readAsDataURL(this.files[0]);
        this.files = [];
    })
    $('#btnCrop').on('click', function(){
        var img = cropper.getDataURL();
        toParentData = cropper.getDataURL();
        $('.cropped').html('');
        $('.cropped').append('<img src="'+img+'" align="absmiddle" style="width:64px;margin-top:4px;border-radius:64px;box-shadow:0px 0px 12px #7E7E7E;" ><p>64px*64px</p>');
        $('.cropped').append('<img src="'+img+'" align="absmiddle" style="width:128px;margin-top:4px;border-radius:128px;box-shadow:0px 0px 12px #7E7E7E;"><p>128px*128px</p>');
        $('.cropped').append('<img src="'+img+'" align="absmiddle" style="width:180px;margin-top:4px;border-radius:180px;box-shadow:0px 0px 12px #7E7E7E;"><p>180px*180px</p>');
    })
    $('#btnZoomIn').on('click', function(){
        cropper.zoomIn();
    })
    $('#btnZoomOut').on('click', function(){
        cropper.zoomOut();
    })
});

    function getBase64(){
        return toParentData;
    }
</script>

</body>
</html>

 CSS代码

@charset "utf-8";
.container {
    width: 400px;
    margin: 40px auto 0 auto;
    position: relative;
    font-family: 微软雅黑;
    font-size: 12px;
}
.container p {
    line-height: 12px;
    line-height: 0px;
    height: 0px;
    margin: 10px;
    color: #bbb
}
.action {
    width: 400px;
    height: 30px;
    margin: 10px 0;
}
.cropped {
    position: absolute;
    right: -230px;
    top: 0;
    width: 200px;
    border: 1px #ddd solid;
    height: 460px;
    padding: 4px;
    box-shadow: 0px 0px 12px #ddd;
    text-align: center;
}
.imageBox {
    position: relative;
    height: 400px;
    width: 400px;
    border: 1px solid #aaa;
    background: #fff;
    overflow: hidden;
    background-repeat: no-repeat;
    cursor: move;
    box-shadow: 4px 4px 12px #B0B0B0; 
}
.imageBox .thumbBox {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 200px;
    height: 200px;
    margin-top: -100px;
    margin-left: -100px;
    box-sizing: border-box;
    border: 1px solid rgb(102, 102, 102);
    box-shadow: 0 0 0 1000px rgba(0, 0, 0, 0.5);
    background: none repeat scroll 0% 0% transparent;
}
.imageBox .spinner {
    position: absolute;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    text-align: center;
    line-height: 400px;
    background: rgba(0,0,0,0.7);
}
.Btnsty_peyton{ float: right;
   width: 66px;
  display: inline-block;
  margin-bottom: 10px;
  height: 57px;
  line-height: 57px;
  font-size: 20px;
  color: #FFFFFF;
  margin:0px 2px;
  background-color: #f38e81;
  border-radius: 3px;
  text-decoration: none;
  cursor: pointer;
  box-shadow: 0px 0px 5px #B0B0B0;
  border: 0px #fff solid;}
/*选择文件上传*/
.new-contentarea {
    width: 165px;
    overflow:hidden;
    margin: 0 auto;
    position:relative;float:left;
}
.new-contentarea label {
    width:100%;
    height:100%;
    display:block;
}
.new-contentarea input[type=file] {
    width:188px;
    height:60px;
    background:#333;
    margin: 0 auto;
    position:absolute;
    right:50%;
    margin-right:-94px;
    top:0;
    right/*\**/:0px\9;
    margin-right/*\**/:0px\9;
    width/*\**/:10px\9;
    opacity:0;
    filter:alpha(opacity=0);
    z-index:2;
}
a.upload-img{
    width:165px;
    display: inline-block;
    margin-bottom: 10px;
    height:57px;
    line-height: 57px;
    font-size: 20px;
    color: #FFFFFF;
    background-color: #f38e81;
    border-radius: 3px;
    text-decoration:none;
    cursor:pointer;
    border: 0px #fff solid;
    box-shadow: 0px 0px 5px #B0B0B0;
}
a.upload-img:hover{
    background-color: #ec7e70;
}

.tc{text-align:center;}
/*www.jq22.com*/

JS代码

"use strict";
(function (factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery'], factory);
    } else {
        factory(jQuery);
    }
}(function ($) {
    var cropbox = function(options, el){
        var el = el || $(options.imageBox),
            obj =
            {
                state : {},
                ratio : 1,
                options : options,
                imageBox : el,
                thumbBox : el.find(options.thumbBox),
                spinner : el.find(options.spinner),
                image : new Image(),
                getDataURL: function ()
                {
                    var width = this.thumbBox.width(),
                        height = this.thumbBox.height(),
                        canvas = document.createElement("canvas"),
                        dim = el.css('background-position').split(' '),
                        size = el.css('background-size').split(' '),
                        dx = parseInt(dim[0]) - el.width()/2 + width/2,
                        dy = parseInt(dim[1]) - el.height()/2 + height/2,
                        dw = parseInt(size[0]),
                        dh = parseInt(size[1]),
                        sh = parseInt(this.image.height),
                        sw = parseInt(this.image.width);

                    canvas.width = width;
                    canvas.height = height;
                    var context = canvas.getContext("2d");
                    context.drawImage(this.image, 0, 0, sw, sh, dx, dy, dw, dh);
                    var imageData = canvas.toDataURL('image/png');
                    return imageData;
                },
                getBlob: function()
                {
                    var imageData = this.getDataURL();
                    var b64 = imageData.replace('data:image/png;base64,','');
                    var binary = atob(b64);
                    var array = [];
                    for (var i = 0; i < binary.length; i++) {
                        array.push(binary.charCodeAt(i));
                    }
                    return  new Blob([new Uint8Array(array)], {type: 'image/png'});
                },
                zoomIn: function ()
                {
                    this.ratio*=1.1;
                    setBackground();
                },
                zoomOut: function ()
                {
                    this.ratio*=0.9;
                    setBackground();
                }
            },
            setBackground = function()
            {
                var w =  parseInt(obj.image.width)*obj.ratio;
                var h =  parseInt(obj.image.height)*obj.ratio;

                var pw = (el.width() - w) / 2;
                var ph = (el.height() - h) / 2;

                el.css({
                    'background-image': 'url(' + obj.image.src + ')',
                    'background-size': w +'px ' + h + 'px',
                    'background-position': pw + 'px ' + ph + 'px',
                    'background-repeat': 'no-repeat'});
            },
            imgMouseDown = function(e)
            {
                e.stopImmediatePropagation();

                obj.state.dragable = true;
                obj.state.mouseX = e.clientX;
                obj.state.mouseY = e.clientY;
            },
            imgMouseMove = function(e)
            {
                e.stopImmediatePropagation();

                if (obj.state.dragable)
                {
                    var x = e.clientX - obj.state.mouseX;
                    var y = e.clientY - obj.state.mouseY;

                    var bg = el.css('background-position').split(' ');

                    var bgX = x + parseInt(bg[0]);
                    var bgY = y + parseInt(bg[1]);

                    el.css('background-position', bgX +'px ' + bgY + 'px');

                    obj.state.mouseX = e.clientX;
                    obj.state.mouseY = e.clientY;
                }
            },
            imgMouseUp = function(e)
            {
                e.stopImmediatePropagation();
                obj.state.dragable = false;
            },
            zoomImage = function(e)
            {
                e.originalEvent.wheelDelta > 0 || e.originalEvent.detail < 0 ? obj.ratio*=1.1 : obj.ratio*=0.9;
                setBackground();
            }

        obj.spinner.show();
        obj.image.onload = function() {
            obj.spinner.hide();
            setBackground();

            el.bind('mousedown', imgMouseDown);
            el.bind('mousemove', imgMouseMove);
            $(window).bind('mouseup', imgMouseUp);
            el.bind('mousewheel DOMMouseScroll', zoomImage);
        };
        obj.image.src = options.imgSrc;
        el.on('remove', function(){$(window).unbind('mouseup', imgMouseUp)});

        return obj;
    };

    jQuery.fn.cropbox = function(options){
        return new cropbox(options, this);
    };
}));

/*www.jq22.com*/

拿到base64编码之后,可以当成字符串传到后台。这里给出JAVA在后台解析base64并存储为文件的代码。

//头像上传
    @ResponseBody
    @RequestMapping(value="/headImg/upload", method={RequestMethod.POST})
    public Result headImgupload(@RequestParam("base64") String base64,HttpServletRequest request) {    
        String username = shiroUtils.getUserName();
        boolean success = true;
          try{  
                  Log.debug("上传文件的数据:"+base64);
                String dataPrix = "";
                String data = "";
                Log.debug("对数据进行判断");
                if(base64 == null || "".equals(base64)){
                    throw new Exception("上传失败,上传图片数据为空");
                }else{
                    String [] d = base64.split("base64,");
                    if(d != null && d.length == 2){
                        dataPrix = d[0];
                        data = d[1];
                    }else{
                        throw new Exception("上传失败,数据不合法");
                    }
                }

                Log.debug("对数据进行解析,获取文件名和流数据");
                String suffix = "";
                if("data:image/jpeg;".equalsIgnoreCase(dataPrix)){//data:image/jpeg;base64,base64编码的jpeg图片数据
                    suffix = ".jpg";
                } else if("data:image/x-icon;".equalsIgnoreCase(dataPrix)){//data:image/x-icon;base64,base64编码的icon图片数据
                    suffix = ".ico";
                } else if("data:image/gif;".equalsIgnoreCase(dataPrix)){//data:image/gif;base64,base64编码的gif图片数据
                    suffix = ".gif";
                } else if("data:image/png;".equalsIgnoreCase(dataPrix)){//data:image/png;base64,base64编码的png图片数据
                    suffix = ".png";
                }else{
                    throw new Exception("上传图片格式不合法");
                }
                String tempFileName = StringUtils.getRandom(6)+"_"+username+"_headImg"+suffix;
                Log.debug("生成文件名为:"+tempFileName);

                //因为BASE64Decoder的jar问题,此处使用spring框架提供的工具包
                byte[] bs = Base64Utils.decodeFromString(data);
                try{
                    //使用apache提供的工具类操作流
                    FileUtils.writeByteArrayToFile(new File(request.getSession().getServletContext().getRealPath("")+Constant.HeadImg, tempFileName), bs);  
                }catch(Exception ee){
                    throw new Exception("上传失败,写入文件失败,"+ee.getMessage());
                }
               System.out.println(request.getSession().getServletContext().getRealPath("")+Constant.HeadImg+"--"+tempFileName);
                Log.debug("上传成功");
                
                //更改用户头像信息
                User user = new User();
                user.setUserName(username);
                user.setHeadImg("/upload/headImg/"+tempFileName);
                userservice.editHeadImg(user);
            }catch (Exception e) {  
                 Log.debug("上传失败,"+e.getMessage());
                success = false;  
            }  
        return new Result(success);
    }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏JackieZheng

探秘Tomcat——启动篇

tomcat作为一款web服务器本身很复杂,代码量也很大,但是模块化很强,最核心的模块还是连接器Connector和容器Container。具体请看下图: ? ...

50070
来自专栏函数式编程语言及工具

Akka(43): Http:SSE-Server Sent Event - 服务端主推消息

   因为我了解Akka-http的主要目的不是为了有关Web-Server的编程,而是想实现一套系统集成的api,所以也需要考虑由服务端主动向客户端发送指令的...

27290
来自专栏haifeiWu与他朋友们的专栏

golang重构博客统计服务

作为一个后端开发,在docker,etcd,k8s等新技术不断涌现的今天,其背后的功臣golang在语言排行榜上持续走高,因此楼主也就开了这次使用golang自...

14120
来自专栏Flutter知识集

Flutter 实践 MVVM

在做Android或iOS开发时,经常会了解到MVC,MVP和MVVM。MVVM在移动端一度被非常推崇,虽然也有不少反对的声音,不过MVVM确实是不错的设计架构...

3.4K50
来自专栏java 成神之路

spring 之 import标签、alias标签、beans标签 解析

604100
来自专栏后端沉思录

Spring源码之解析并注册BeanDefinition(一)

最近有空把Spring加载bean流程复习了一下,也乘机可以做个整理.首先还是看下入口代码,本文主要讲解析及注册BeanDefinition整体加载流程:

21210
来自专栏MasiMaro 的技术博文

hook键盘驱动中的分发函数实现键盘输入数据的拦截

我自己在看《寒江独钓》这本书的时候,书中除了给出了利用过滤的方式来拦截键盘数据之外,也提到了另外一种方法,就是hook键盘分发函数,将它替换成我们自己的,然后再...

11020
来自专栏雪胖纸的玩蛇日常

Uncaught SyntaxError: Unexpected token ' in JSON at position 1

1.4K30
来自专栏Golang语言社区

用Go实现一门解释型语言

A interpreter language implementation in Go

9720
来自专栏Golang语言社区

GoLang并发控制(下)

context的字面意思是上下文,是一个比较抽象的词,字面上理解就是上下层的传递,上会把内容传递给下,在go中程序单位一般为goroutine,这里的上下文便是...

34030

扫码关注云+社区

领取腾讯云代金券