Springboot+Vue-Cropper realizes the effect of avatar cutting and uploading

Springboot+Vue-Cropper realizes the effect of avatar cutting and uploading

Use the Vue-Cropper component to upload avatars. For your reference, the specific content is as follows

Effect display

Take a look at the effect first. If the effect does not meet your needs, there is no need to waste time reading it down.

After clicking on the picture

Then click Upload Picture to upload successfully. The specific effect and page layout are like this

Front-end code

It is recommended to read the official documentation of vue-cropper in detail before use. It is introduced in detail and can be modified according to your needs: link

One more thing: The elelment-ui component library is used in the entire project. Import element-ui before use

I will add comments to the code to explain the explanation. After all, to know the reason, you must know the origin.

<template>
  <div style="height: 800px;">
    <el-tabs v-model="activeName" @tab-click="handleClick" class="tabs">
      <el-tab-pane label="Personal Information" name="first">
      </el-tab-pane>
      <el-tab-pane label="Change avatar" name="second">
        <div class="avatar_header">
          <span>Current avatar</span>
        </div>
        <div class="avatar_current">
          <img :src="currentimg">
        </div>
        <div class="avatar_select">
          <!-- This is done here because the original <input type="file"> tag is too ugly. You can try it yourself to see how ugly it is. So use button to control the trigger input to select the file-->
          <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">Select an image</el-button>

          <el-button type="success" style="margin-left:100px;" @click="uploadImg('blob')">Upload picture</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="Change Password" 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, //Here I save the user information in Vuex for management previews:{},
      option:{
        img:'', //Address of cropped image,
        outputSize:1, //The quality of the cropped image is optional (0,1,-1)
        outputType:'jpeg', //Format of cropped image info:true, //Image size information canScale:true, //Whether to allow wheel zoom autoCrop:true, //Whether to generate screenshot frame by default autoCropWidth:240,
        autoCropHeight:240, //Default screenshot frame size fixed:true, //Whether to enable fixed ratio of screenshot frame width and height fixedNumber:[1,1], //The aspect ratio of the screenshot frame,
        full:false, //Crop the image in its original proportion without distortion fixedBox:true, //Fixed screenshot box size, no changes allowed canMove:false, //Can the uploaded image be moved?
        canMoveBox:true, //Can the screenshot box be dragged original:false, //Uploaded images are rendered according to the original ratio centerBox:false, //Is the screenshot box limited to the image height:true, //Whether to output proportional images according to the device's DPR infoTrue:false, //true is to display the actual output image width and height, false is to display the screenshot box width and height,
        maxImgSize:3000, //Limit the maximum width and height of the image enlarge:1, //Image output ratio multiples according to the screenshot frame mode:'400px 300px' //Image rendering method}
    }
  },
  methods: {
    // Tab switching calling method, not important! Deleted some unnecessary code handleClick(){
    },

    //Select the image calling method selectAvatar(){
      this.$refs.uploads.click();
    },
    // The real method for selecting images, let's name it this way for now setImage(e){
      let file = e.target.files[0];
      if (!/\.(jpg|jpeg|png|JPG|PNG)$/.test(e.target.value)) {
        // this.$message.info("Incorrect image type");
        console.log("Incorrect image type");
        return false;
      }
      //Convert to blob. The purpose of using blob is to display the uploaded image on the page. let reader = new FileReader();
      // The onload method is triggered after the file is read successfully. reader.onload = (e) => {
        let data;
        // To display on the page, convert to url format if (typeof e.target.result === 'object') {
          data = window.URL.createObjectURL(new Blob([e.target.result]))
        }else{
          data = e.target.result
        }
        this.option.img = data
        //Convert to base64
      }
      reader.readAsDataURL(file)
    },

    realTime(data){
      this.previews = data;
    },
    // Initialization function imgLoad(msg){
      console.log("Tool initialization function ====="+msg);
    },

    // Calling method for uploading avatar uploadImg(type){
      let _this = this;
      if(type === 'blob'){
        //Get the blob data type of the screenshot this.$refs.cropper.getCropBlob(async (data) => {
          let formData = new FormData();
          // Send data to the backend. Please process it according to your own backend logic. I save the username in Vuex and can directly name it 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); //Save the new avatar back to Vuex
              _this.$router.go(0); //Refresh the webpage}
          })
        })
      }

    }
  },

  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>

Backend code

Here we first describe the backend processing logic:

1. After obtaining the avatar, the picture will be saved on the cloud server. Here we set our own static file directory in drive D, see static_root.
2. Then save the URL of the image on the cloud server in the backend MySQL database.
3. Return a successful upload message to the front end, carrying the URL of the image so that the image can be accessed through the URL and displayed on the front end.

Controller Layer

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

The Service layer is directly implemented on impl

 //This is the imported toolkit, which needs to be installed in pom.xml. import cn.hutool.core.io.FileUtil;
    //Some port information @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 {
        //Get the name of the original file String originalFilename = file.getOriginalFilename();
// String rootFilePath = System.getProperty("user.dir")+"/src/main/resources/files/"+originalFilename;
        //Get the file path String rootFilePath = static_root + "/avatar/" + originalFilename;
        //Save in fileFileUtil.writeBytes(file.getBytes(),rootFilePath);
        //The url used to access the image
        String avatar = ip+":"+port+"/avatar/"+originalFilename;
        try{
            //Store avatar information in the database userMapper.updateAvatar(avatar,username);
            //Self-encapsulated Result result return class return Result.success(200,"Upload successful",avatar);
        }catch (Exception e){
            System.out.println(e);
            return Result.fail("Upload failed");
        }
    }

Mapper persistence layer

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

mapper.xml file

<?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>

About the encapsulation of the Result class

public class Result {
    private int code; //200 is normal, non-200 indicates abnormality private String msg;
    private Object data;
    public static Result success(Object data){
        return success(200,"Operation successful",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;}
}

After the image is saved on the cloud server, it can be accessed directly through the URL. Here I show this effect locally. Only when this effect is achieved can the front end access the image in the img tag.

The above is the full content of this article. I hope it will be helpful for everyone’s study. I also hope that everyone will support 123WORDPRESS.COM.

You may also be interested in:
  • vue-cropper component realizes image cutting and uploading
  • vue-cropper plug-in realizes the encapsulation of image capture and upload component
  • Detailed explanation of how to use vue-cropper, a Vue image cropping plugin
  • Vue-cropper The basic principles and ideas of picture cropping
  • Encapsulating Vue based on cropper.js to realize online image cropping component function
  • Do you know how to use vue-cropper to crop pictures in vue?

<<:  A brief discussion on docker compose writing rules

>>:  Workerman writes the example code of mysql connection pool

Recommend

JavaScript quickly implements calendar effects

This article example shares the specific code of ...

SQL Get stored procedure return data process analysis

This article mainly introduces the analysis of th...

How to write the style of CSS3 Tianzi grid list

In many projects, it is necessary to implement th...

An example of using CSS methodologies to achieve modularity

1. What are CSS methodologies? CSS methodologies ...

Sample code for implementing interface signature with Vue+Springboot

1. Implementation ideas The purpose of interface ...

How to show or hide common icons on the desktop in Windows Server 2012

Windows Server 2012 and Windows Server 2008 diffe...

Problems with index and FROM_UNIXTIME in mysql

Zero, Background I received a lot of alerts this ...

The iframe refresh method is more convenient

How to refresh iframe 1. To refresh, you can use j...

A solution to the abnormal exit of Tomcat caused by semaphore

I'm playing with big data recently. A friend ...

Example code for implementing fullpage.js full-screen scrolling effect with CSS

When I was studying CSS recently, I found that I ...

HTML tbody usage

Structured Table (IExplore Only) 1) Group by rows ...

Detailed tutorial on configuring nginx for https encrypted access

environment: 1 CentOS Linux release 7.5.1804 (Cor...

How to implement the webpage anti-copying function (with cracking method)

By right-clicking the source file, the following c...

Complete steps for uninstalling MySQL database

The process of completely uninstalling the MySQL ...

iFrame is a great way to use it as a popup layer to cover the background

I have been working on a project recently - Budou ...