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标签中访问到图片。

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

以上是 Springboot+Vue-Cropper实现头像剪切上传效果 的全部内容, 来源链接: utcz.com/p/239594.html

回到顶部