最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Springboot+Vue-Cropper實現(xiàn)頭像剪切上傳效果

 更新時間:2021年08月23日 09:17:10   作者:月下獨Coding  
這篇文章主要為大家詳細(xì)介紹了Springboot+Vue-Cropper實現(xiàn)頭像剪切上傳效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

使用Vue-Cropper這一組件實現(xiàn)頭像上傳,供大家參考,具體內(nèi)容如下

效果展示

先看一下效果吧,如果效果不能滿足你的需求,就不必再浪費時間往下看了

點擊選擇圖片之后

然后再點擊上傳圖片就可以上傳成功,具體效果和頁面布局就是這樣

前端代碼

使用先建議詳細(xì)閱讀vue-cropper官方文檔,里面介紹的很詳細(xì),可以根據(jù)自己的需求進(jìn)行修改:鏈接

補充一點:整個項目中使用了elelment-ui組件庫,使用前先導(dǎo)入element-ui

關(guān)于解釋我會在代碼中添加注釋,畢竟知其然要知其所以然,學(xué)習(xí)還是得有溯源精神

<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>當(dāng)前頭像</span>
        </div>
        <div class="avatar_current">
          <img :src="currentimg">
        </div>
        <div class="avatar_select">
          <!-- 這里這樣做是因為
          原來的 <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,         //上傳圖片是否可以移動,
        canMoveBox:true,       //截圖框是否可以拖動
        original:false,        //上傳圖片按照原始比例渲染
        centerBox:false,       //截圖框是否被限制在圖片里面
        height:true,           //是否按照設(shè)備的dpr,輸出等比例圖片
        infoTrue:false,        //true為展示真實輸出圖片寬高,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、獲取到頭像后,會將圖片保存在云服務(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實現(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直接訪問到圖片了,這里我本地展示這一效果,實現(xiàn)了這一效果,前端才能夠在img標(biāo)簽中訪問到圖片。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • vue實現(xiàn)導(dǎo)入json解析成動態(tài)el-table樹表格

    vue實現(xiàn)導(dǎo)入json解析成動態(tài)el-table樹表格

    本文主要介紹了vue實現(xiàn)導(dǎo)入json解析成動態(tài)el-table樹表格,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • 使用elementUI的表格table給列添加樣式

    使用elementUI的表格table給列添加樣式

    這篇文章主要介紹了使用elementUI的表格table給列添加樣式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • 2種在vue項目中使用百度地圖的簡單方法

    2種在vue項目中使用百度地圖的簡單方法

    在本篇文章中我們給大家整理了2種關(guān)于VUE項目中使用百度地圖的最簡單的方法,非常實用,一起來學(xué)習(xí)下。
    2018-09-09
  • elementUI實現(xiàn)級聯(lián)選擇器

    elementUI實現(xiàn)級聯(lián)選擇器

    這篇文章主要為大家詳細(xì)介紹了elementUI實現(xiàn)級聯(lián)選擇器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • vue執(zhí)行配置選項npm?run?serve的本質(zhì)圖文詳解

    vue執(zhí)行配置選項npm?run?serve的本質(zhì)圖文詳解

    本地開發(fā)一般通過執(zhí)行npm run serve命令來啟動項目,那這行命令到底存在什么魔法?下面這篇文章主要給大家介紹了關(guān)于vue執(zhí)行配置選項npm?run?serve的本質(zhì)的相關(guān)資料,需要的朋友可以參考下
    2023-05-05
  • vue項目中定時器無法清除的原因解決

    vue項目中定時器無法清除的原因解決

    頁面有定時器,并且定時器在離開頁面時,有清除,本文主要介紹了vue項目中定時器無法清除的原因解決,具有一定的參考價值,感興趣的可以了解一下
    2024-02-02
  • Vue+ElementUI踩坑之動態(tài)顯示/隱藏表格的列el-table-column問題

    Vue+ElementUI踩坑之動態(tài)顯示/隱藏表格的列el-table-column問題

    這篇文章主要介紹了Vue+ElementUI踩坑之動態(tài)顯示/隱藏表格的列el-table-column問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • element tree懶加載:load="loadNode"只觸發(fā)一次的解決方案

    element tree懶加載:load="loadNode"只觸發(fā)一次的解決方案

    本文主要介紹了element tree懶加載:load="loadNode"只觸發(fā)一次的解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • vue-router 源碼之實現(xiàn)一個簡單的 vue-router

    vue-router 源碼之實現(xiàn)一個簡單的 vue-router

    這篇文章主要介紹了vue-router 源碼之實現(xiàn)一個簡單的 vue-router,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • vue實現(xiàn)點擊隱藏與顯示實例分享

    vue實現(xiàn)點擊隱藏與顯示實例分享

    在本篇文章中小編給大家分享了vue如何實現(xiàn)點擊隱藏與顯示的相關(guān)內(nèi)容,有需要的朋友們跟著學(xué)習(xí)下。
    2019-02-02

最新評論

博野县| 金川县| 庄河市| 西乌| 黎川县| 英吉沙县| 柳江县| 吴江市| 会泽县| 阿坝| 沙洋县| 涞水县| 宜君县| 鄂托克前旗| 平舆县| 汉源县| 太白县| 潞城市| 北安市| 武川县| 岢岚县| 怀柔区| 海南省| 闵行区| 龙南县| 顺昌县| 三门县| 交城县| 富锦市| 徐水县| 霍城县| 海淀区| 聂荣县| 岳阳市| 固镇县| 黄大仙区| 承德县| 甘德县| 凯里市| 姜堰市| 中卫市|