Springboot+Vue-Cropper實(shí)現(xiàn)頭像剪切上傳效果
使用Vue-Cropper這一組件實(shí)現(xiàn)頭像上傳,供大家參考,具體內(nèi)容如下
效果展示
先看一下效果吧,如果效果不能滿足你的需求,就不必再浪費(fèi)時(shí)間往下看了

點(diǎn)擊選擇圖片之后

然后再點(diǎn)擊上傳圖片就可以上傳成功,具體效果和頁面布局就是這樣
前端代碼
使用先建議詳細(xì)閱讀vue-cropper官方文檔,里面介紹的很詳細(xì),可以根據(jù)自己的需求進(jìn)行修改:鏈接
補(bǔ)充一點(diǎn):整個(gè)項(xiàng)目中使用了elelment-ui組件庫,使用前先導(dǎo)入element-ui
關(guān)于解釋我會(huì)在代碼中添加注釋,畢竟知其然要知其所以然,學(xué)習(xí)還是得有溯源精神
<template>
<div style="height: 800px;">
<el-tabs v-model="activeName" @tab-click="handleClick" class="tabs">
<el-tab-pane label="個(gè)人信息" name="first">
</el-tab-pane>
<el-tab-pane label="更換頭像" name="second">
<div class="avatar_header">
<span>當(dāng)前頭像</span>
</div>
<div class="avatar_current">
<img :src="currentimg">
</div>
<div class="avatar_select">
<!-- 這里這樣做是因?yàn)?
原來的 <input type="file">標(biāo)簽太丑了,可以自己去嘗試一下,看看有多丑
所以使用button來控制觸發(fā)input來進(jìn)行選擇文件
-->
<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進(jìn)行管理
previews:{},
option:{
img:'', //裁剪圖片的地址,
outputSize:1, //裁剪生成的圖片質(zhì)量可選(0,1,-1)
outputType:'jpeg', //裁剪生成圖片的格式
info:true, //圖片大小信息
canScale:true, //是否允許滾輪縮放
autoCrop:true, //是否默認(rèn)生成截圖框
autoCropWidth:240,
autoCropHeight:240, //默認(rèn)生成截圖框大小
fixed:true, //是否開啟截圖框?qū)捀吖潭ū壤?
fixedNumber:[1,1], //截圖框的寬高比,
full:false, //按原比例裁剪圖片,不失真
fixedBox:true, //固定截圖框大小,不允許改變
canMove:false, //上傳圖片是否可以移動(dòng),
canMoveBox:true, //截圖框是否可以拖動(dòng)
original:false, //上傳圖片按照原始比例渲染
centerBox:false, //截圖框是否被限制在圖片里面
height:true, //是否按照設(shè)備的dpr,輸出等比例圖片
infoTrue:false, //true為展示真實(shí)輸出圖片寬高,false展示看到的截圖框?qū)捀撸?
maxImgSize:3000, //限制圖片最大寬度和高度
enlarge:1, //圖片根據(jù)截圖框輸出比例倍數(shù)
mode:'400px 300px' //圖片渲染方式
}
}
},
methods: {
// 標(biāo)簽頁切換調(diào)用方法,不重要!刪掉了一些不必要的代碼
handleClick(){
},
// 選擇圖片調(diào)用方法
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;
}
//轉(zhuǎn)化為blob,使用blob是為了在頁面中展示上傳的那張圖片
let reader = new FileReader();
// 文件讀取成功后觸發(fā)onload方法
reader.onload = (e) => {
let data;
// 要在頁面中展示,轉(zhuǎn)化為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
//轉(zhuǎn)化為base64
}
reader.readAsDataURL(file)
},
realTime(data){
this.previews = data;
},
//初始化函數(shù)
imgLoad(msg){
console.log("工具初始化函數(shù)====="+msg);
},
// 頭像上傳調(diào)用方法
uploadImg(type){
let _this = this;
if(type === 'blob'){
//獲取截圖的blob數(shù)據(jù)類型
this.$refs.cropper.getCropBlob(async (data) => {
let formData = new FormData();
// 發(fā)數(shù)據(jù)傳遞到后端,注意這里請根據(jù)自己的后端邏輯進(jìn)行處理,我是將用戶名保存在Vuex中,可以直接進(jìn)行命名
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); //刷新網(wǎng)頁
}
})
})
}
}
},
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、獲取到頭像后,會(huì)將圖片保存在云服務(wù)器上,這里我們設(shè)定的自己的靜態(tài)文件目錄在D盤,見static_root。
2、然后將圖片在云服務(wù)器上的url保存在后端mysql數(shù)據(jù)庫中。
3、返回給前端上傳成功的消息,攜帶圖片的url這樣就可以通過url訪問到這張圖片,從而在前端進(jìn)行顯示。
Controller層
@ResponseBody
@PostMapping("/updateavatar")
public Result updateAvatar(@RequestParam("username") String username,@RequestParam("file") MultipartFile file) throws IOException {
return userService.uploadAvatar(username,file);
}
Service層直接上impl實(shí)現(xiàn)
//這是導(dǎo)的工具包,需要在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{
//頭像信息存入數(shù)據(jù)庫
userMapper.updateAvatar(avatar,username);
//自己封裝的Result結(jié)果返回類
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>
關(guān)于Result結(jié)果類的封裝
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;}
}
當(dāng)圖片保存在云服務(wù)器上后,就可以通過url直接訪問到圖片了,這里我本地展示這一效果,實(shí)現(xiàn)了這一效果,前端才能夠在img標(biāo)簽中訪問到圖片。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 使用Springboot+Vue實(shí)現(xiàn)文件上傳和下載功能
- 基于SpringBoot和Vue實(shí)現(xiàn)頭像上傳與回顯功能
- Vue?+?SpringBoot?實(shí)現(xiàn)文件的斷點(diǎn)上傳、秒傳存儲(chǔ)到Minio的操作方法
- springboot+vue實(shí)現(xiàn)阿里云oss大文件分片上傳的示例代碼
- Java實(shí)現(xiàn)大文件的分片上傳與下載(springboot+vue3)
- springboot整合vue2-uploader實(shí)現(xiàn)文件分片上傳、秒傳、斷點(diǎn)續(xù)傳功能
- 利用Springboot+vue實(shí)現(xiàn)圖片上傳至數(shù)據(jù)庫并顯示的全過程
- Vue+Element+Springboot圖片上傳的實(shí)現(xiàn)示例
- springboot + vue+elementUI實(shí)現(xiàn)圖片上傳功能
相關(guān)文章
基于Vue2.0和Typescript實(shí)現(xiàn)多主題切換的示例
本文主要介紹了基于Vue2.0和Typescript實(shí)現(xiàn)多主題切換的示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04
vue項(xiàng)目tween方法實(shí)現(xiàn)返回頂部的示例代碼
這篇文章主要介紹了vue項(xiàng)目tween方法實(shí)現(xiàn)返回頂部,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-03-03
Vue3 setup語法糖銷毀一個(gè)或多個(gè)定時(shí)器(setTimeout/setInterval)
這篇文章主要給大家介紹了關(guān)于Vue3 setup語法糖銷毀一個(gè)或多個(gè)定時(shí)器(setTimeout/setInterval)的相關(guān)資料,vue是單頁面應(yīng)用,路由切換后,定時(shí)器并不會(huì)自動(dòng)關(guān)閉,需要手動(dòng)清除,當(dāng)頁面被銷毀時(shí),清除定時(shí)器即可,需要的朋友可以參考下2023-10-10
Vue中控制v-for循環(huán)次數(shù)的實(shí)現(xiàn)方法
今天小編就為大家分享一篇Vue中控制v-for循環(huán)次數(shù)的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09
vue常用指令實(shí)現(xiàn)學(xué)生錄入系統(tǒng)的實(shí)戰(zhàn)
本文主要介紹了vue常用指令實(shí)現(xiàn)學(xué)生錄入系統(tǒng)的實(shí)戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
vue2中基于vue-simple-upload實(shí)現(xiàn)文件分片上傳組件功能
這篇文章主要介紹了vue2中基于vue-simple-upload的文件分片上傳組件,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-06-06

