Upload files locally in the project (the usage of cropper)

Scenario: The project needs to upload local files (pictures, videos, etc.)

html provided input Tags can upload files
< input type="file" />
//This will generate a button on the page, click to upload the file
//But it is generally not used in this way, because the native button is not beautiful

Add hideen attribute to the input tag, then the input tag will be hidden

 <input type="file" hidden ref="file" @change="onFileChange" />

The change event is triggered when a local file is selected and confirmed, but it does not trigger every time. If the two selected files are the same, it will not trigger the second time. The solution is explained below.

There is such a scene, click to change the avatar, then you can trigger the hidden input box by clicking the button to change the avatar

 //Click on the avatar
    onChangePhoto() {
      //Because the input box has been hidden, the click event of the original input is triggered by clicking on other boxes
      this.$refs.file.click();
    },

When the local file is selected and press OK, the input change event will be triggered

 //When does the @change event trigger? For example on the pc side: it is triggered after selecting a computer file and clicking OK
    onFileChange() {
      /*
      this.$refs.file.files[0] 
      What is obtained is a complex object, which contains the size of the picture, the type of the picture, the current time
       console.log(1111, this.$refs.file.files[0]);
      */
      /* 
      Entering window.URL.createObjectURL will get a url path in http format
     */
      this.img = window.URL.createObjectURL(this.$refs.file.files[0]);

      //Show popup
      this.userPhotoShow = true;
      //When the same file is selected for the second time, the @change function will not be triggered, we can make the value of this.$refs.file equal to empty
      this.$refs.file.value = "";
    },
   
    

Prior to Gecko 1.9.2, through the input element, only one file could be selected at a time, which meant that the FileList object on the files property of the input element could contain only one file anyway. As of Gecko 1.9.2, if an input element has the multiple attribute, it can be used to select multiple files. When multiple files are selected, an array of fileList is returned

<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
<!-- multiple Properties allow user to select multiple files -->

<input id="myfiles" multiple type="file">

</body>

<script>

var pullfiles=function(){
    // love the query selector
    var fileInput = document.querySelector("#myfiles");
    var files = fileInput.files;
    // Get the number of selected files
    var fl = files.length;
    var i = 0;

    while ( i < fl) {
        // localize file var in the loop
        var file = files[i];
        alert(file.name);
        i++;
    }
}

// Set the change event handler
document.querySelector("#myfiles").onchange=pullfiles;

</script>

</html>

Image upload example

Since uploading pictures will definitely involve picture cropping, you need to use the third-party library cropperjs, please refer to the specific usage method official documentation
first

npm install cropperjs

Set up photo boxes

img {
  display: block;

  /* This rule is very important, please don't ignore this */
  max-width: 100%;
}

Introduce corpper and its style in the corresponding component

import "cropperjs/dist/cropper.css";
import Cropper from "cropperjs";

Avatar cropping

Set the style of the crop box in the mounted function

mounted() {
    //Get the dom element node,
    const image = this.$refs.img;
    //cropper is the data in data initialized to null, newcropper returns the cropper object, a complex object
    this.cropper = new Cropper(image, {
      viewMode: 1, //Try mode, the clipping frame cannot exceed the picture
      dragMode: "move", //Move mode, move can move pictures
      aspectRatio: 1, //The ratio of the fixed cropping frame, usually a square, choose 1/1, abbreviated 1
      autoCropArea: 1, //The size of the custom crop area, it should be a number between 0 and 1. Define the auto crop area size (percentage)
      cropBoxMovable: false, //Enable this option to move the crop box by dragging.
      cropBoxResizable: false, //Enables resizable crop box size
      background: false, //Do not enable the default background
    });
  },

save update

After the cropping is completed, send the request and send the image to the server

If Content-Type is required to be application/json , data is a normal object {}
If Content-Type is required to be multipart/form-data , then data pass FormData Object
Looking at all data interfaces, you will find that most of them require Content-Type requirements to be application/json
Generally, only the data interface related to file upload requires Content-Type to be multipart/form-data
This time pass a FormData object

For server-based cropping, use: getData method, which gets the cropped area parameters. Requires back-end interface cooperation

If it is pure client-side image cropping, use: getCroppedCanvas method, which gets the cropped image object (similar to the file object obtained by the URL.createObjectURL method).

 methods: {
    confirm() {
   
      // This time pass a FormData object
   
      //Pure client-side cropped file, use getCroppedCanvas() to get the cropped file object
      this.cropper.getCroppedCanvas().toBlob((blob) => {
        const formData = new FormData();
        //Add a new property value to FormData. If the property value corresponding to FormData exists, it will not overwrite the original value, but add a new value. If the property does not exist, add a new property value.
        formData.append("photo", blob);
        this.updataPhoto(formData);
      });
    },
    
    async updataPhoto(formData) {
      this.$toast.loading({
        duration: 0, // keep showing toast
        forbidClick: true,
        message: "Loading",
      });
      try {
        const { data } = await updataUserPhoto(formData);
        //close popup
        this.$emit("close");
        //success tips
        this.$toast.success("Successfully modified");
        //update view
        this.$emit("updataPhoto", data.data.photo);
      } catch (error) {
        console.log(error);
        this.$toast.faile("Identity expired,Please try logging in again");
      }
    },
  },

Tags: Javascript Front-end html5

Posted by savedlema on Sun, 15 May 2022 02:03:26 +0300