Springboot + Vue-Cropper realisiert den Effekt des Avatar-Ausschneidens und -Hochladens

Springboot + Vue-Cropper realisiert den Effekt des Avatar-Ausschneidens und -Hochladens

Verwenden Sie die Vue-Cropper-Komponente, um Avatare hochzuladen. Zu Ihrer Information ist der spezifische Inhalt wie folgt

Effektanzeige

Schauen Sie sich zunächst die Wirkung an. Wenn die Wirkung nicht Ihren Anforderungen entspricht, müssen Sie keine Zeit mit dem Lesen verschwenden.

Nach dem Klick auf das Bild

Klicken Sie dann auf Bild hochladen, um den Upload erfolgreich abzuschließen. Der spezifische Effekt und das Seitenlayout sind wie folgt

Front-End-Code

Es wird empfohlen, vor der Verwendung die offizielle Dokumentation von vue-cropper ausführlich zu lesen. Sie wird ausführlich vorgestellt und kann entsprechend Ihren Anforderungen geändert werden: Link

Noch etwas: Die Komponentenbibliothek element-ui wird im gesamten Projekt verwendet. Importieren Sie element-ui vor der Verwendung

Ich werde dem Code Kommentare hinzufügen, um die Erklärung zu erläutern. Um den Grund zu kennen, muss man schließlich den Ursprung kennen.

<Vorlage>
  <div Stil="Höhe: 800px;">
    <el-tabs v-model="aktiverName" @tab-click="handleClick" class="tabs">
      <el-tab-pane label="Persönliche Informationen" name="Vorname">
      </el-tab-pane>
      <el-tab-pane label="Avatar ändern" name="second">
        <div Klasse="avatar_header">
          <span>Aktueller Avatar</span>
        </div>
        <div Klasse="avatar_current">
          <img :src="aktuellesimg">
        </div>
        <div Klasse="Avatar_Auswahl">
          <!-- Dies wird hier gemacht, weil das ursprüngliche Tag <input type="file"> zu hässlich ist. Sie können es selbst ausprobieren, um zu sehen, wie hässlich es ist. Verwenden Sie also die Schaltfläche, um den Trigger-Eingang zum Auswählen der Datei zu steuern-->
          <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">Wählen Sie ein Bild aus</el-button>

          <el-button type="success" style="margin-left:100px;" @click="uploadImg('blob')">Bild hochladen</el-button>
        </div>

        <div Klasse="cropper_box">
        <div Klasse="avatar_cropper">
          <vue-cropper
            ref="Beschneider"
            :img="Option.img"
            :Ausgabegröße="Option.Ausgabegröße"
            :Ausgabetyp="Option.Ausgabetyp"
            :info="option.info"
            :canScale="Option.canScale"
            :autoCrop="Option.autoCrop"
            :autoCropWidth="Option.autoCropWidth"
            :autoCropHeight="Option.autoCropHeight"
            :fest="Option.fest"
            :festeNummer="Option.festeNummer"
            :full="Option.full"
            :fixedBox="Option.fixedBox"
            :kannVerschieben="Option.kannVerschieben"
            :kannBox verschieben="Option.kannBox verschieben"
            :original="Option.original"
            :centerBox="Option.centerBox"
            :Höhe="Option.Höhe"
            :infoTrue="option.infoTrue"
            :maxImgSize="Option.maxImgSize"
            :vergrößern="option.vergrößern"
            :mode="Option.Modus"
            @realTime="Echtzeit"
            @imgLoad="imgLoad">
          </vue-cropper>
        </div>

        <div Klasse = "show_preview" :style = "{'Breite': Vorschau.w + 'px', 'Höhe': Vorschau.h + 'px', 'Überlauf': 'versteckt',
          'Rand': '5px'}">
          <div:style="Vorschau.div">
            <img :src="option.img" :style="vorschau.img">
          </div>
        </div>
        </div>
      </el-tab-pane>

      <el-tab-pane label="Passwort ändern" name="third">

      </el-tab-pane>
    </el-tabs>
  </div>
</Vorlage>

<Skript>
importiere qs von „qs“
importiere { VueCropper } von 'vue-cropper'

Standard exportieren {
  Daten() {
    zurückkehren {
      activeName:'zweite',
      currentimg:this.$store.getters.getAvatar, //Hier speichere ich die Benutzerinformationen in Vuex für die Verwaltung von Vorschauen:{},
      Option:{
        img:'', //Adresse des zugeschnittenen Bildes,
        outputSize:1, //Die Qualität des zugeschnittenen Bildes ist optional (0,1,-1)
        outputType:'jpeg', //Format des zugeschnittenen Bildes info:true, //Informationen zur Bildgröße canScale:true, //Ob das Zoomen mit dem Rad erlaubt ist autoCrop:true, //Ob standardmäßig ein Screenshot-Rahmen generiert werden soll autoCropWidth:240,
        autoCropHeight:240, //Standardgröße des Screenshot-Rahmens fixed:true, //Ob ein festes Verhältnis zwischen Breite und Höhe des Screenshot-Rahmens aktiviert werden soll fixedNumber:[1,1], //Das Seitenverhältnis des Screenshot-Rahmens,
        full:false, //Bild ohne Verzerrung in seiner Originalproportion zuschneiden fixedBox:true, //Feste Größe der Screenshot-Box, keine Änderungen zulässig canMove:false, //Kann das hochgeladene Bild verschoben werden?
        canMoveBox:true, //Kann die Screenshot-Box gezogen werden? original:false, //Hochgeladene Bilder werden entsprechend dem Originalverhältnis gerendert centerBox:false, //Ist die Screenshot-Box auf das Bild beschränkt? height:true, //Sollen proportionale Bilder entsprechend den DPR-Informationen des Geräts ausgegeben werden?True:false, //true bedeutet, die tatsächliche Breite und Höhe des Ausgabebildes anzuzeigen, false bedeutet, die Breite und Höhe der Screenshot-Box anzuzeigen,
        maxImgSize:3000, //Begrenzung der maximalen Breite und Höhe des Bildes enlarge:1, //Bildausgabeverhältnis wird entsprechend dem Screenshot-Rahmenmodus vervielfacht:'400px 300px' //Bild-Rendering-Methode}
    }
  },
  Methoden: {
    //Tab-Umschaltung - Aufrufmethode, nicht wichtig! Unnötigen Code gelöscht handleClick(){
    },

    //Bild auswählen, Methode selectAvatar() aufrufen{
      dies.$refs.uploads.click();
    },
    // Die eigentliche Methode zum Auswählen von Bildern, nennen wir sie vorerst so setImage(e){
      let Datei = e.Zieldateien[0];
      wenn (!/\.(jpg|jpeg|png|JPG|PNG)$/.test(e.ziel.wert)) {
        // this.$message.info("Falscher Bildtyp");
        console.log("Falscher Bildtyp");
        gibt false zurück;
      }
      //In Blob konvertieren. Der Zweck der Verwendung von Blob besteht darin, das hochgeladene Bild auf der Seite anzuzeigen. let reader = new FileReader();
      // Die Methode onload wird ausgelöst, nachdem die Datei erfolgreich gelesen wurde. reader.onload = (e) => {
        Daten lassen;
        // Zur Anzeige auf der Seite in URL-Format konvertieren, if (typeof e.target.result === 'object') {
          Daten = Fenster.URL.createObjectURL(neuer Blob([e.target.result]))
        }anders{
          Daten = e.Ziel.Ergebnis
        }
        diese.option.img = Daten
        //In Base64 konvertieren
      }
      reader.readAsDataURL(Datei)
    },

    Echtzeit(Daten){
      this.previews = Daten;
    },
    // Initialisierungsfunktion imgLoad(msg){
      console.log("Tool-Initialisierungsfunktion ====="+msg);
    },

    // Aufrufmethode zum Hochladen des Avatars uploadImg(type){
      lass _this = dies;
      wenn(Typ === 'Blob'){
        //Blob-Datentyp des Screenshots abrufen this.$refs.cropper.getCropBlob(async (data) => {
          let formData = neue FormData();
          // Daten an das Backend senden. Bitte verarbeiten Sie diese nach Ihrer eigenen Backend-Logik. Ich speichere den Benutzernamen in Vuex und kann ihn direkt benennen formData.append("username", this.$store.getters.getUsername);
          formData.append('Datei',Daten,dies.$store.getters.getUsername+".jpg");
          dies.axios.post('/updateavatar',formData).dann(Funktion(Antwort){
            console.log(Antwort);
            wenn(Antwort.Daten.Code == 200){
              console.log(Antwort);
              _this.currentimg = Antwort.Daten.Daten;
              _this.$store.commit('setAvatar',response.data.data); //Speichern Sie den neuen Avatar wieder in Vuex
              _this.$router.go(0); //Webseite aktualisieren}
          })
        })
      }

    }
  },

  Komponenten: {VueCropper}
};

</Skript>

<Stilbereich>
.tab-erstellen{
  Position: absolut;
  rechts: 80px;
  oben: 115px;
  Rand oben: 5px;
  Z-Index: 999;
}

.avatar_header{
  Breite: 100 %;
  Höhe: 50px;
  Schriftgröße: 14;
  Zeilenhöhe: 50px;
  Schriftstärke: 550;
  Polsterung links: 20px;
  Textausrichtung: links;
}

.avatar_current{
  Breite: 100 %;
  Höhe: 260px;
  Textausrichtung: links;
}
.avatar_current img{
  Breite: 240px;
  Höhe: 240px;
  Rand links: 20px;

}
.avatar_auswahl{
  Textausrichtung: links;
}

.cropper_box{
  Textausrichtung: links;
  Position: relativ;
}
.avatar_cropper{
  Rand oben: 40px;
  Höhe: 350px;
  Breite: 450px;
  Anzeige: Inline-Block;
}

.show_preview{
  Anzeige: Inline-Block;
  Position: absolut;
  oben: 30px;
  links: 500px;
}


</Stil>

Backend-Code

Hier beschreiben wir zunächst die Backend-Verarbeitungslogik:

1. Nachdem der Avatar erhalten wurde, wird das Bild auf dem Cloud-Server gespeichert. Hier legen wir unser eigenes statisches Dateiverzeichnis auf Laufwerk D fest, siehe static_root.
2. Speichern Sie dann die URL des Bildes auf dem Cloud-Server in der MySQL-Datenbank im Backend.
3. Senden Sie eine Meldung über den erfolgreichen Upload an das Front-End zurück. Diese enthält die URL des Bildes, sodass über die URL auf das Bild zugegriffen und es im Front-End angezeigt werden kann.

Controller-Ebene

@AntwortBody
@PostMapping("/updateavatar")
    öffentliches Ergebnis updateAvatar(@RequestParam("Benutzername") String Benutzername,@RequestParam("Datei") MultipartFile Datei) löst IOException aus {
        returniere userService.uploadAvatar(Benutzername,Datei);
    }

Die Service-Schicht wird direkt auf impl implementiert

 //Dies ist das importierte Toolkit, das in pom.xml installiert werden muss. import cn.hutool.core.io.FileUtil;
    //Einige Portinformationen @Value("${server.port}")
    privater String-Port;

    private statische endgültige String-IP = "http://localhost";

    private statische endgültige Zeichenfolge static_root = "D:/devplatform_files";


    @Überschreiben
    öffentliches Ergebnis uploadAvatar(String username, MultipartFile file) throws IOException {
        //Name der Originaldatei abrufen String originalFilename = file.getOriginalFilename();
// String rootFilePath = System.getProperty("user.dir")+"/src/main/resources/files/"+originalFilename;
        //Dateipfad abrufen String rootFilePath = static_root + "/avatar/" + originalFilename;
        //In Datei speichernFileUtil.writeBytes(file.getBytes(),rootFilePath);
        //Die URL, die für den Zugriff auf das Bild verwendet wird
        Zeichenfolge Avatar = IP+":"+Port+"/Avatar/"+Originaldateiname;
        versuchen{
            //Avatar-Informationen in der Datenbank speichern userMapper.updateAvatar(avatar,username);
            //Selbstgekapseltes Ergebnis Ergebnis-Rückgabeklasse return Result.success(200,"Upload erfolgreich",Avatar);
        }catch (Ausnahme e){
            System.out.println(e);
            return Result.fail("Hochladen fehlgeschlagen");
        }
    }

Mapper-Persistenzschicht

@Mapper
@Repository
öffentliche Schnittstelle UserMapper{
    String getAvatarByUsername(String Benutzername);
}

Datei „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">
    <Aktualisierungs-ID="Aktualisierungs-Avatar">
        Benutzer aktualisieren, Avatar festlegen = #{avatar}, wobei Benutzername = #{Benutzername}
    </Aktualisieren>
</mapper>

Über die Kapselung der Result-Klasse

öffentliche Klasse Ergebnis {
    privater Int-Code; //200 ist normal, ein Wert ungleich 200 weist auf eine Anomalie hin private String msg;
    private Objektdaten;
    öffentliches statisches Ergebnis erfolgreich (Objektdaten) {
        return success(200,"Vorgang erfolgreich",Daten);
    }
    öffentliches statisches Ergebnis erfolgreich (String-Nachricht) {
        Rückgabewert: Erfolg (200, Nachricht, null);
    }
    öffentliches statisches Ergebnis erfolgreich (int Code, String-Nachricht, Objektdaten) {
        Ergebnis r = neues Ergebnis();
        r.setCode(code);
        r.setData(Daten);
        r.setMsg(msg);
        Rückkehr r;
    }
    öffentliches statisches Ergebnis fehlgeschlagen (String msg) {
        Rückgabewert: fehlgeschlagen (400, Nachricht, null);
    }
    öffentliches statisches Ergebnis fehlgeschlagen (String msg, Objektdaten) {
        Rückgabewert: fehlgeschlagen (400, Nachricht, Daten);
    }
    öffentliches statisches Ergebnis fehlgeschlagen (int Code, String-Nachricht, Objektdaten) {
        Ergebnis r = neues Ergebnis();
        r.setCode(code);
        r.setData(Daten);
        r.setMsg(msg);
        Rückkehr r;
    }
    public int getCode() {Rückgabecode;}
    öffentliche void setCode(int code) {this.code = code;}
    öffentliche Zeichenfolge getMsg() {return msg;}
    öffentliche void setMsg(String msg) {this.msg = msg;}
    öffentliches Objekt getData() {return data;}
    öffentliche void setData(Objektdaten) {this.data = data;}
}

Nachdem das Bild auf dem Cloud-Server gespeichert wurde, kann direkt über die URL darauf zugegriffen werden. Hier zeige ich diesen Effekt lokal. Erst wenn dieser Effekt erreicht ist, kann das Frontend auf das Bild im img-Tag zugreifen.

Das Obige ist der vollständige Inhalt dieses Artikels. Ich hoffe, er wird für jedermanns Studium hilfreich sein. Ich hoffe auch, dass jeder 123WORDPRESS.COM unterstützen wird.

Das könnte Sie auch interessieren:
  • Die Komponente vue-cropper realisiert das Zuschneiden und Hochladen von Bildern
  • Das Vue-Cropper-Plugin realisiert die Kapselung der Bildaufnahme- und Upload-Komponente
  • Detaillierte Erklärung zur Verwendung von vue-cropper, einem Vue-Plugin zum Zuschneiden von Bildern
  • Vue-Cropper Die Grundprinzipien und Ideen des Bildzuschneidens
  • Kapselung von Vue basierend auf cropper.js zur Realisierung der Online-Komponentenfunktion zum Zuschneiden von Bildern
  • Wissen Sie, wie Sie mit Vue-Cropper Bilder in Vue zuschneiden?

<<:  Eine kurze Diskussion über Schreibregeln für Docker Compose

>>:  Workerman schreibt den Beispielcode des MySQL-Verbindungspools

Artikel empfehlen

Lösung für Indexfehler in MySQL aufgrund unterschiedlicher Feldzeichensätze

Was ist ein Index? Warum einen Index erstellen? I...

Vue: Detaillierte Erklärung von Speicherlecks

Was ist ein Speicherleck? Ein Speicherleck bedeut...

Lösen Sie das Problem des Mac Docker x509-Zertifikats

Frage Kürzlich musste ich mich bei einem privaten...

Asynchroner Lebenszyklus von AsyncHooks in Node8

Async Hooks ist eine neue Funktion von Node8. Sie...

JavaScript-Grundlagen: Fehlererfassungsmechanismus

Inhaltsverzeichnis Vorwort Error-Objekt werfen ve...

So implementieren Sie Eingabe-Checkboxen zur Erweiterung der Klickreichweite

XML/HTML-CodeInhalt in die Zwischenablage kopiere...

Fallstudie zum Löschen und Neuinstallieren eines Mac-Knotens

Mac-Knoten löschen und neu installieren löschen K...