Springboot+Vue-Cropper实现头像剪切上传效果

使用Vue-Cropper这一组件实现头像上传,供大家参考,具体内容如下

效果展示

先看一下效果吧,如果效果不能满足你的需求,就不必再浪费时间往下看了

点击选择图片之后

然后再点击上传图片就可以上传成功,具体效果和页面布局就是这样

前端代码

使用先建议详细阅读vue-cropper官方文档,里面介绍的很详细,可以根据自己的需求进行修改:链接

补充一点:整个项目中使用了elelment-ui组件库,使用前先导入element-ui

关于解释我会在代码中添加注释,毕竟知其然要知其所以然,学习还是得有溯源精神

<template>
  <div style="height: 800px;">
    <el-tabs v-model="activeName" @tab-click="handleClick" class="tabs">
      <el-tab-pane label="个人信息" name="first">
      </el-tab-pane>
      <el-tab-pane label="更换头像" name="second">
        <div class="avatar_header">
          <span>当前头像</span>
        </div>
        <div class="avatar_current">
          <img :src="currentimg">
        </div>
        <div class="avatar_select">
          <!-- 这里这样做是因为
          原来的 <input type="file">标签太丑了,可以自己去尝试一下,看看有多丑
          所以使用button来控制触发input来进行选择文件
          -->
          <input type="file"  ref="uploads" id="uploads" accept="image/png, image/jpeg, image/gif, image/jpg" hidden @change="setImage($event)">
          <el-button type="primary" @click="selectAvatar">选择图片</el-button>

          <el-button type="success" style="margin-left:100px;" @click="uploadImg('blob')">上传图片</el-button>
        </div>

        <div class="cropper_box">
        <div class="avatar_cropper">
          <vue-cropper
            ref="cropper"
            :img="option.img"
            :outputSize="option.outputSize"
            :outputType="option.outputType"
            :info="option.info"
            :canScale="option.canScale"
            :autoCrop="option.autoCrop"
            :autoCropWidth="option.autoCropWidth"
            :autoCropHeight="option.autoCropHeight"
            :fixed="option.fixed"
            :fixedNumber="option.fixedNumber"
            :full="option.full"
            :fixedBox="option.fixedBox"
            :canMove="option.canMove"
            :canMoveBox="option.canMoveBox"
            :original="option.original"
            :centerBox="option.centerBox"
            :height="option.height"
            :infoTrue="option.infoTrue"
            :maxImgSize="option.maxImgSize"
            :enlarge="option.enlarge"
            :mode="option.mode"
            @realTime="realTime"
            @imgLoad="imgLoad">
          </vue-cropper>
        </div>

        <div class="show_preview" :style="{'width': previews.w + 'px', 'height': previews.h + 'px',  'overflow': 'hidden',
          'margin': '5px'}">
          <div :style="previews.div">
            <img :src="option.img" :style="previews.img">
          </div>
        </div>
        </div>
      </el-tab-pane>

      <el-tab-pane label="修改密码" name="third">

      </el-tab-pane>
    </el-tabs>
  </div>
</template>

<script>
import qs from 'qs'
import { VueCropper }  from 'vue-cropper'

export default {
  data() {
    return {
      activeName:'second',
      currentimg:this.$store.getters.getAvatar,    //这里我是将用户信息保存在Vuex进行管理
      previews:{},
      option:{
        img:'',                //裁剪图片的地址,
        outputSize:1,          //裁剪生成的图片质量可选(0,1,-1)
        outputType:'jpeg',     //裁剪生成图片的格式
        info:true,             //图片大小信息
        canScale:true,         //是否允许滚轮缩放
        autoCrop:true,         //是否默认生成截图框
        autoCropWidth:240,
        autoCropHeight:240,    //默认生成截图框大小
        fixed:true,            //是否开启截图框宽高固定比例
        fixedNumber:[1,1],     //截图框的宽高比,
        full:false,            //按原比例裁剪图片,不失真
        fixedBox:true,         //固定截图框大小,不允许改变
        canMove:false,         //上传图片是否可以移动,
        canMoveBox:true,       //截图框是否可以拖动
        original:false,        //上传图片按照原始比例渲染
        centerBox:false,       //截图框是否被限制在图片里面
        height:true,           //是否按照设备的dpr,输出等比例图片
        infoTrue:false,        //true为展示真实输出图片宽高,false展示看到的截图框宽高,
        maxImgSize:3000,       //限制图片最大宽度和高度
        enlarge:1,             //图片根据截图框输出比例倍数
        mode:'400px 300px'     //图片渲染方式
      }
    }
  },
  methods: {
    // 标签页切换调用方法,不重要!删掉了一些不必要的代码
    handleClick(){
    },

    // 选择图片调用方法
    selectAvatar(){
      this.$refs.uploads.click();
    },
    // 真正的选择图片方法,姑且先这么命名吧
    setImage(e){
      let file = e.target.files[0];
      if (!/\.(jpg|jpeg|png|JPG|PNG)$/.test(e.target.value)) {
        // this.$message.info("图片类型不正确");
        console.log("图片类型不正确");
        return false;
      }
      //转化为blob,使用blob是为了在页面中展示上传的那张图片
      let reader = new FileReader();
      // 文件读取成功后触发onload方法
      reader.onload = (e) => {
        let data;
        // 要在页面中展示,转化为url形式
        if(typeof e.target.result === 'object'){
          data = window.URL.createObjectURL(new Blob([e.target.result]))
        }else{
          data = e.target.result
        }
        this.option.img = data
        //转化为base64
      }
      reader.readAsDataURL(file)
    },

    realTime(data){
      this.previews = data;
    },
    //初始化函数
    imgLoad(msg){
      console.log("工具初始化函数====="+msg);
    },

    // 头像上传调用方法
    uploadImg(type){
      let _this = this;
      if(type === 'blob'){
        //获取截图的blob数据类型
        this.$refs.cropper.getCropBlob(async (data) => {
          let formData = new FormData();
          // 发数据传递到后端,注意这里请根据自己的后端逻辑进行处理,我是将用户名保存在Vuex中,可以直接进行命名
          formData.append("username",this.$store.getters.getUsername);
          formData.append('file',data,this.$store.getters.getUsername+".jpg");
          this.axios.post('/updateavatar',formData).then(function(response){
            console.log(response);
            if(response.data.code == 200){
              console.log(response);
              _this.currentimg = response.data.data;
              _this.$store.commit('setAvatar',response.data.data);   //把新头像重新保存回Vuex
              _this.$router.go(0);                                   //刷新网页
              }
          })
        })
      }

    }
  },

  components:{VueCropper}
};

</script>

<style scoped>
.tab-create{
  position: absolute;
  right: 80px;
  top: 115px;
  margin-top: 5px;
  z-index: 999;
}

.avatar_header{
  width: 100%;
  height: 50px;
  font-size: 14;
  line-height: 50px;
  font-weight: 550;
  padding-left: 20px;
  text-align: left;
}

.avatar_current{
  width: 100%;
  height: 260px;
  text-align: left;
}
.avatar_current img{
  width: 240px;
  height: 240px;
  margin-left: 20px;

}
.avatar_select{
  text-align: left;
}

.cropper_box{
  text-align: left;
  position: relative;
}
.avatar_cropper{
  margin-top: 40px;
  height: 350px;
  width: 450px;
  display: inline-block;
}

.show_preview{
  display: inline-block;
  position: absolute;
  top:30px;
  left: 500px;
}

</style>

后端代码

这里先讲述后端的处理逻辑:

1、获取到头像后,会将图片保存在云服务器上,这里我们设定的自己的静态文件目录在D盘,见static_root。
2、然后将图片在云服务器上的url保存在后端mysql数据库中。
3、返回给前端上传成功的消息,携带图片的url这样就可以通过url访问到这张图片,从而在前端进行显示。

Controller层

@ResponseBody
@PostMapping("/updateavatar")
    public Result updateAvatar(@RequestParam("username") String username,@RequestParam("file") MultipartFile file) throws IOException {
        return userService.uploadAvatar(username,file);
    }

Service层直接上impl实现

 //这是导的工具包,需要在pom.xml安装依赖
 import cn.hutool.core.io.FileUtil;
    //一些端口信息
    @Value("${server.port}")
    private String port;

    private static final String ip = "http://localhost";

    private static final String static_root = "D:/devplatform_files";

    @Override
    public Result uploadAvatar(String username, MultipartFile file) throws IOException {
        //获取原文件的名称
        String originalFilename = file.getOriginalFilename();
//      String rootFilePath = System.getProperty("user.dir")+"/src/main/resources/files/"+originalFilename;
        //获取到文件路径
        String rootFilePath = static_root +"/avatar/"+ originalFilename;
        //保存在文件中
        FileUtil.writeBytes(file.getBytes(),rootFilePath);
        //图片访问用到的url
        String avatar = ip+":"+port+"/avatar/"+originalFilename;
        try{
            //头像信息存入数据库
            userMapper.updateAvatar(avatar,username);
            //自己封装的Result结果返回类
            return Result.success(200,"上传成功",avatar);
        }catch (Exception e){
            System.out.println(e);
            return Result.fail("上传失败");
        }
    }

mapper持久层

@Mapper
@Repository
public interface UserMapper{
    String getAvatarByUsername(String username);
}

mapper.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.devplatform.mapper.UserMapper">
    <update id="updateAvatar">
        update user set avatar = #{avatar} where username = #{username}
    </update>
</mapper>

关于Result结果类的封装

public class Result {
    private int code;   //200是正常   非200表示异常
    private String msg;
    private Object data;
    public static Result success(Object data){
        return success(200,"操作成功",data);
    }
    public static Result success(String msg){
        return success(200,msg,null);
    }
    public static Result success(int code, String msg, Object data){
        Result r = new Result();
        r.setCode(code);
        r.setData(data);
        r.setMsg(msg);
        return r;
    }
    public static Result fail(String msg){
        return fail(400, msg, null);
    }
    public static Result fail(String msg, Object data){
        return fail(400, msg, data);
    }
    public static Result fail(int code, String msg, Object data){
        Result r = new Result();
        r.setCode(code);
        r.setData(data);
        r.setMsg(msg);
        return r;
    }
    public int getCode() {return code;}
    public void setCode(int code) {this.code = code;}
    public String getMsg() {return msg;}
    public void setMsg(String msg) {this.msg = msg;}
    public Object getData() {return data;}
    public void setData(Object data) {this.data = data;}
}

当图片保存在云服务器上后,就可以通过url直接访问到图片了,这里我本地展示这一效果,实现了这一效果,前端才能够在img标签中访问到图片。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • node+vue实现用户注册和头像上传的实例代码

    最近正好空闲,写了个实用注册代码,分享给大家,有需要的朋友可以了解一下 数据库我使用的是MongoDB. 首先做文件上传,要保证协议里面的'Content-Type'为'multipart/form-data'. 注册的步骤: 将用户名密码,图片等提交给node端 node端将图片保存到服务器,图片路径及注册用户的个人信息保存到mongodb数据库. 项目目录如下,注册功能只是其中的第一步: 前端框架使用的是vue.js,ajax使用的是vue的组件vue-resource. 前端上传代码如下

  • Vue头像处理方案小结

    个人思路 获取后台返回头像url,判断图片宽度,高度. 如果宽度>高度, 使其高度填充盒子 两边留白. 如果宽度<高度,使得宽度填充盒子 上下留白. 效果图: 缺陷:懒加载图片 会出现闪烁 代码实现 <template> // 外面要给一个div并且限制宽度和高度,text-align center,overflow hidden <div class="head"> // userInfoList.avatar 是后台返回给我的头像URL <

  • 详解vue更改头像功能实现

    如上图所示:需要完成的功能是点击更改头像,获取本地文件库,选择图片后将原始图片替换.这里我就直接用html文件引入vue来简单实现在这功能,代码如下: HTML: <div id="app"> <div class="item_bock head_p"> <div class="head_img"> <img :src="userInfo.avatar"/> <--图片地址

  • vue中使用axios post上传头像/图片并实时显示到页面的方法

    在前端开发中,为了更好的用户体验,在头像上传时会先将图片显示到页面然后点击保存按钮 完成图片的上传成功 代码部分有参考他人的写法. html代码: <div id="myPhoto" v-show="personalPhoto"> <div class="viewPhoto"> <img src="" alt="" id="portrait"style=&q

  • 详解Vue+axios+Node+express实现文件上传(用户头像上传)

    Vue 页面的代码 <label for='my_file' class="theme-color"> <mu-icon left value="backup"></mu-icon> 修改头像 </label> <input type="file" ref="upload" name="avatar" id='my_file' style="d

  • vue.js+elementUI实现点击左右箭头切换头像功能(类似轮播图效果)

    1.效果图如下 2.vue代码如下 <el-carousel type="card" arrow="always" :loop="false" :initial-index="1" indicator-position="none" :autoplay="false"> <el-carousel-item v-for="(items, index) in it

  • Springboot+Vue-Cropper实现头像剪切上传效果

    使用Vue-Cropper这一组件实现头像上传,供大家参考,具体内容如下 效果展示 先看一下效果吧,如果效果不能满足你的需求,就不必再浪费时间往下看了 点击选择图片之后 然后再点击上传图片就可以上传成功,具体效果和页面布局就是这样 前端代码 使用先建议详细阅读vue-cropper官方文档,里面介绍的很详细,可以根据自己的需求进行修改:链接 补充一点:整个项目中使用了elelment-ui组件库,使用前先导入element-ui 关于解释我会在代码中添加注释,毕竟知其然要知其所以然,学习还是得有

  • Vue项目实现html5图片上传的示例代码

    目录 图例 1.选择图片 2.预览图片 2.1添加图片预览代码 两种方法的对比 3.裁剪图片 4.上传 选择图片 -> 预览图片 -> 裁剪图片 -> 上传图片 我会以事例贯穿图片接下来,就详细的介绍每个步骤具体实现. 图例 1.选择图片 选择图片有什么好讲的呢?不就一个 input[type=file] ,然后点击就可以了吗?确实是这样的,但是,我们想要做得更加的友好一些,比如需要过滤掉非图片文件, 或只允许从摄像头拍照获取图片等,还是需要进行一些简单配置的. 下面就先来看看最简单的选

  • node.js(express)中使用Jcrop进行图片剪切上传功能

    需求说明 简单来说就是要实现用户上传头像,并且要保存用户裁切后的部分作为用户头像. 第一步,选择图片: 第二步,在弹窗页面中展现并进行裁切: 第三步,点击"保存",上传服务器. 实现过程 说来有点坎坷,相当于做了2遍,走了弯路. 第1遍是用户一选择图片,就进行了上传,然后返回一个地址,所以在弹层上展现的图片已经是服务器上的图片了,然后进行裁切,再保存. 第2遍找到的一个方法,是在第1遍做到裁切处理时候想到的,即弹层展现的是用户机器上选择的图片,不用先上传,但是用image/base64

  • vue实现图片裁剪后上传

    本文实例为大家分享了vue实现图片裁剪后上传的具体代码,供大家参考,具体内容如下 一.背景 目前负责的系统(商城后台管理系统)里面有这么一个需求,为了配合前台的展示,上传的商品图片比较必须是1:1的正方形.(其它地方有时会有5:4或者16:9的需求,但较少).所以需要对上传的图片先进行裁剪,并且按要求只能裁剪为1:1,然后在进行上传. 当然,为了兼容系统其它地方有5:4或者16:9的图片比例需求,需要给出一个参数,可以随时控制图片裁剪的比例. 二.使用什么插件实现 使用 vue-cropper

  • SpringBoot+微信小程序实现文件上传与下载功能详解

    目录 1.文件上传 1.1 后端部分 1.2 小程序前端部分 1.3 实现效果 2.文件下载 2.1 后端部分 2.2 小程序前端部分 2.3 实现效果 1.文件上传 1.1 后端部分 1.1.1 引入Apache Commons FIleUpload组件依赖 <!--文件上传与下载相关的依赖--> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fil

  • vue中用H5实现文件上传的方法实例代码

    整理文档,搜刮出一个vue中用H5实现文件上传的方法实例代码,稍微整理精简一下做下分享. 1.图片上传 <img v-if="personInfo.photoUrl" :src="headPreFix + personInfo.photoUrl" style="height:126px;max-width:133px;margin: 25px 0;"> <img v-else src="../../assets/def

  • 使用canvas实现仿新浪微博头像截取上传功能

    最近看到微博头像上传功能很感兴趣,于是就使用canvas写了一个,本文写的不好还请见谅.本程序目前在谷歌浏览器和火狐浏览器测试可用,ie浏览器无法支持. 因为ie的安全机制不允许img使用本地路径,所以若想ie支持本程序,必须先将图片上传,然后给img对象上传后的图片地址. 我在这里没写,是因为暂时没写上传功能的后端代码,并且还不确定有没有更好的解决办法. 如下是新浪的 如下是我做的截取部分 代码: var canvas = document.getElementById('canvas'),

  • vue使用axios实现文件上传进度的实时更新详解

    axios 简介 axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征: 从浏览器中创建 XMLHttpRequest 从 node.js 发出 http 请求 支持 Promise API 拦截请求和响应 转换请求和响应数据 取消请求 自动转换JSON数据 客户端支持防止 CSRF/XSRF 引入方式: $ npm install axios //使用淘宝源 $ cnpm install axios //或者使用cdn: <script s

  • vue 实现剪裁图片并上传服务器功能

    预览链接点击预览 效果图如下所示,大家感觉不错,请参考实现代码. 需求 [x] 预览:根据选择图像大小自适应填充左侧裁剪区域 [x] 裁剪:移动裁剪框右侧预览区域可实时预览 [x] 上传&清空:点击确认上传裁剪图片,点击取消按钮清空图像 [ ] 裁剪框可调节大小 实现步骤 methods:funName() - 对应源码中methods中的funName方法 data:dataName - 对应源码中data中的dataName数据 1. 图片选择与读取 选择图片 :(methods:selec

随机推荐