vue-cropper component realizes image cutting and uploading

vue-cropper component realizes image cutting and uploading

This article shares the specific code of the vue-cropper component to implement image cutting and uploading for your reference. The specific content is as follows

These few days, I had some free time and practiced uploading avatars with vue and spring boot, so I wrote it down and hope it will be helpful for future development.

Introduction of vue-cropper in vue

1. Introduction into the component

import { VueCropper } from 'vue-cropper' 
components:
  VueCropper,
},

2. Global introduction

Configure the following code in main.js

import VueCropper from 'vue-cropper' 

Vue.use(VueCropper)

3. Usage Examples

vue file

<template>
  <el-dialog
    title="Edit avatar"
    :visible.sync="dialogFormVisible"
    :close-on-click-modal="false"
    append-to-body
  >
    <label class="btn" for="uploads">Select an image</label>
    <input
      type="file"
      id="uploads"
      :value="imgFile"
      style="position:absolute; clip:rect(0 0 0 0);"
      accept="image/png, image/jpeg, image/gif, image/jpg"
      @change="uploadImg($event, 1)"
    >
    <div style="margin-left:20px;">
      <div class="show-preview" :style="{'overflow': 'hidden', 'margin': '5px'}">
        <div :style="previews.div" class="preview" style="width: 40px;height: 40px;">
          <img :src="previews.url" :style="previews.img">
        </div>
      </div>
    </div>
    <div class="cut">
      <vueCropper
        ref="cropper"
        :img="option.img"
        :outputSize="option.size"
        :outputType="option.outputType"
        :info="true"
        :full="option.full"
        :canMove="option.canMove"
        :canMoveBox="option.canMoveBox"
        :original="option.original"
        :autoCrop="option.autoCrop"
        :autoCropWidth="option.autoCropWidth"
        :autoCropHeight="option.autoCropHeight"
        :fixedBox="option.fixedBox"
        @realTime="realTime"
        @imgLoad="imgLoad"
      ></vueCropper>
    </div>
    <div slot="footer" class="dialog-footer">
      <el-button @click="dialogFormVisible = false" size="small">Cancel</el-button>
      <el-button type="primary" @click="finish('blob')" size="small">OK</el-button>
    </div>
  </el-dialog>
</template>

<script>
import { VueCropper } from "vue-cropper";
export default {
  components:
    VueCropper
  },
  data() {
    return {
      previews: {},
      model: false,
      modelSrc: "",
      fileName: "",
      imgFile: "",
      dialogFormVisible: false,
      option: {
        img: "",
        outputSize: 1, //Image quality after cutting (0.1-1)
        full: false, // Output the original image proportion screenshot props name full
        outputType: "png",
        canMove: true,
        original: false,
        canMoveBox: true,
        autoCrop: true,
        autoCropWidth: 40,
        autoCropHeight: 40,
        fixedBox: true
      }
    };
  },
  methods: {
    //Upload the picture (click the upload button)
    finish(type) {
      let selft = this;
      let formData = new FormData();
      // Outputif (type === "blob") {
        selft.$refs.cropper.getCropBlob(data => {
          let img = window.URL.createObjectURL(data);
          selft.model = true;
          selft.modelSrc = img;
          formData.append("file", data, selft.fileName);
          selft.$api.writer.userUpload(formData, r => {
            if (r.code) {
              selft.$alert.error(r.msg);
            } else {
              selft.$message({
                message: r.data.msg,
                type: "success"
              });
              selft.$store.state.userInfo = r.data.data;
              selft.dialogFormVisible = false;
            }
          });
        });
      } else {
        this.$refs.cropper.getCropData(data => {});
      }
    },
    //Select a local image uploadImg(e, num) {
      console.log("uploadImg");
      var selft = this;
      //Upload picture var file = e.target.files[0];
      selft.fileName = file.name;
      if (!/\.(gif|jpg|jpeg|png|bmp|GIF|JPG|PNG)$/.test(e.target.value)) {
        alert("The image type must be one of .gif, jpeg, jpg, png, bmp");
        return false;
      }
      var reader = new FileReader();
      reader.onload = e => {
        let data;
        if (typeof e.target.result === "object") {
          // Convert Array Buffer to blob. If it is base64, it is not needed. data = window.URL.createObjectURL(new Blob([e.target.result]));
        } else {
          data = e.target.result;
        }
        if (num === 1) {
          selft.option.img = data;
        } else if (num === 2) {
          selft.example2.img = data;
        }
      };
      // Convert to base64
      // reader.readAsDataURL(file)
      // Convert to blob
      reader.readAsArrayBuffer(file);
    },
    show() {
      this.dialogFormVisible = true;
    },
    // Real-time preview function realTime(data) {
      console.log("realTime");
      this.previews = data;
    },
    imgLoad(msg) {
      console.log("imgLoad");
      console.log(msg);
    }
  }
};
</script>

<style lang="less">
@import "./userLogo.less";
</style>

less file

.cut {
    width: 300px;
    height: 300px;
    margin: 0px auto;
}

.hh {
    .el-dialog__header {
        padding: 0px;
        line-height: 2;
        background-color: #f3f3f3;
        height: 31px;
        border-bottom: 1px solid #e5e5e5;
        background: #f3f3f3;
        border-top-left-radius: 5px;
        border-top-right-radius: 5px;
    }
    .el-dialog__title {
        float: left;
        height: 31px;
        color: #4c4c4c;
        font-size: 12px;
        line-height: 31px;
        overflow: hidden;
        margin: 0;
        padding-left: 10px;
        font-weight: bold;
        text-shadow: 0 1px 1px #fff;
    }
    .el-dialog__headerbtn {
        position: absolute;
        top: 8px;
        right: 10px;
        padding: 0;
        background: 0 0;
        border: none;
        outline: 0;
        cursor: pointer;
        font-size: 16px;
    }
}

.btn {
    display: inline-block;
    line-height: 1;
    white-space: nowrap;
    cursor: pointer;
    background: #fff;
    border: 1px solid #c0ccda;
    color: #1f2d3d;
    text-align: center;
    box-sizing: border-box;
    outline: none;
    //margin: 20px 10px 0px 0px;
    padding: 9px 15px;
    font-size: 14px;
    border-radius: 4px;
    color: #fff;
    background-color: #50bfff;
    border-color: #50bfff;
    transition: all 0.2s ease;
    text-decoration: none;
    user-select: none;
}

.show-preview {
    flex: 1;
    -webkit-flex: 1;
    display: flex;
    display: -webkit-flex;
    justify-content: center;
    -webkit-justify-content: center;
    .preview {
        overflow: hidden;
        border-radius: 50%;
        border: 1px solid #cccccc;
        background: #cccccc;
    }
}

Configure the Content-Type of axios when sending a request

// http request interceptor axios.interceptors.request.use(
  config => {debugger
    let token = sessionStorage.getItem('token')
    if (token) {
      config.headers.Authorization = token;
    }
    if (config && config.url && config.url.indexOf('upload') > 0) {
      config.headers['Content-Type'] = 'multipart/form-data'
    }
    return config
  },
  err => {
    return Promise.reject(err)
  }
)

Boot controller

@RequestMapping("/upload")
 public ResultData upload(@RequestParam("file") MultipartFile file) {
  return userService.upload(file);
 }

boot service

@Override
 public ResultData upload(MultipartFile file) {
  if (!file.isEmpty()) {
   
   StringBuffer requestURL = sessionUtil.getRequestURL();
   int end = requestURL.indexOf("/user/upload");
   String basePath = requestURL.substring(0, end);
   String savePath = basePath + "/static/img/logo/";
   // Get the file name, including the suffix String fileName = file.getOriginalFilename();

   String saveDbPath = savePath + fileName;

   // Stored in this path: This path is the static file in the project directory: (Note: You may need to create this file yourself)
   // The reason for putting it under static is that it stores static file resources, that is, it can be accessed by entering the local server address and adding the file name through the browser String path = ClassUtils.getDefaultClassLoader().getResource("").getPath() + "static/img/logo/";

   // This method is a wrapper for writing files. In the util class, import the package to use it. The method will be given later. try {
    FileUtil.fileupload(file.getBytes(), path, fileName);
    // Then create the corresponding entity class, add the following path, and then write User through the database operation method user = sessionUtil.getSessionUser();
    user.setLogo(saveDbPath);
    User whereUser = new User();
    whereUser.setId(user.getId());
    ConfigHelper.update(user, "user", whereUser);
    Map<String, Object> map = new HashMap<>();
    map.put("msg", "Avatar modified successfully");
    map.put("data", user);
    return ResultData.ok(map);
   } catch (IOException e) {
    log.error("Picture upload ==》" + e.getMessage());
    e.printStackTrace();
    return ResultData.failed(e.getMessage());
   } catch (Exception e) {
    log.error("Last picture ==》" + e.getMessage());
    e.printStackTrace();
    return ResultData.failed(e.getMessage());
   }

  } else {
   return ResultData.failed("Upload image failed");
  }
 }

Finish

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:
  • Springboot+Vue-Cropper realizes the effect of avatar 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?

<<:  How to run MySQL using docker-compose

>>:  How to install MySQL and MariaDB in Docker

Recommend

mysql8.0.11 winx64 installation and configuration tutorial

The installation tutorial of mysql 8.0.11 winx64 ...

Install mysql5.7 on Ubuntu 18.04

Ubuntu 18.04 installs mysql 5.7 for your referenc...

Complete steps to configure basic user authentication at the Nginx level

Preface Application scenario: probably the intern...

Implementation of form submission in html

Form submission code 1. Source code analysis <...

MySQL quickly inserts 100 million test data

Table of contents 1. Create a table 1.1 Create te...

A brief analysis of the use of the HTML webpack plugin

Using the html-webpack-plugin plug-in to start th...

Detailed explanation of MySQL combined query

Using UNION Most SQL queries consist of a single ...

Solve the pitfall of storing boolean type values ​​in localstorage

LocalStorage stores Boolean values Today, when I ...

How to create dynamic QML objects in JavaScript

1. Dynamically create objects There are two ways ...

Detailed explanation of MySql slow query analysis and opening slow query log

I have also been researching MySQL performance op...

Tutorial on installing MySQL 5.7.28 on CentOS 6.2 (mysql notes)

1. Environmental Preparation 1.MySQL installation...