萌新用vue + axios + formdata 上传文件的爬坑之路
https://blog.csdn.net/qq_41688165/article/details/80834842
结合vue-cropper与element ui实现头像图片剪切上传
https://www.jianshu.com/p/039cfd0dfd05
<template>
<div class="certification-mask">
<div class="certification-box">
<div class="certification-top align-justify-items">修改用户头像</div>
<div @click="$emit('certification-close')" class="certification-close">
<img src="../assets/alert_close.png">
</div>
<div class="cropper-content clearfix">
<div class="cropper-left">
<div class="cropper">
<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 class="cropper-operate">
<button class="el-button is-circle el-button--primary" @click="rotateRight">
<svg t="1580884496485" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1400" width="20" height="20"><path d="M138.72 335.55l4.84-2.8a19 19 0 0 1 26 6.94l23.16 40c57.86-151.64 214.17-254.64 390.84-230.62 163 22.17 291.67 154.12 310.25 317.61C918.81 686.65 747.44 873 532.54 873a362.58 362.58 0 0 1-265.35-115c-12-12.77-3.19-33.64 14.31-33.64a32 32 0 0 1 22.84 9.4c71.09 72.28 176.25 110.94 289.46 90C726 799.19 829.09 691.58 848.91 558.58 878.52 360 725.47 189.27 532.54 189.27c-136 0-252.08 84.86-298.43 204.48l39.18-22.67a21.82 21.82 0 0 1 21.86 37.78L212 456.95a21.82 21.82 0 0 1-29.82-8 22 22 0 0 1-1.06-2.1l-49.38-85.34a19 19 0 0 1 6.98-25.96z" p-id="1401" fill="#ffffff"></path></svg>
</button>
<button class="el-button is-circle el-button--success" @click="rotateLeft">
<svg t="1580884444251" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1166" width="20" height="20"><path d="M886.74 335.55l-4.84-2.8a19 19 0 0 0-26 6.94l-23.16 40C774.88 228.08 618.56 125.08 441.9 149.11c-163 22.17-291.67 154.12-310.25 317.61C106.65 686.65 278 873 492.92 873a362.58 362.58 0 0 0 265.34-115c12-12.77 3.19-33.64-14.31-33.64a32 32 0 0 0-22.84 9.4C650 806 544.86 844.69 431.65 823.7c-132.22-24.51-235.28-132.12-255.11-265.12C146.93 360 300 189.27 492.92 189.27c136 0 252.08 84.86 298.43 204.48l-39.18-22.67a21.82 21.82 0 0 0-21.86 37.78l83.1 48.09a21.82 21.82 0 0 0 29.82-8 22 22 0 0 0 1.06-2.1l49.38-85.34a19 19 0 0 0-6.93-25.96z" p-id="1167" fill="#ffffff"></path></svg>
</button>
<button style="padding: 10px;" class="el-button is-circle el-button--danger" @click="changeScale(1)">
<svg t="1580884167725" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2247" width="16" height="16"><path d="M863.328262 481.340895l-317.344013 0.099772L545.984249 162.816826c0-17.664722-14.336138-32.00086-32.00086-32.00086s-31.99914 14.336138-31.99914 32.00086l0 318.400215-322.368714-0.17718c-0.032684 0-0.063647 0-0.096331 0-17.632039 0-31.935493 14.239806-32.00086 31.904529-0.096331 17.664722 14.208843 32.031824 31.871845 32.095471l322.59234 0.17718 0 319.167424c0 17.695686 14.336138 32.00086 31.99914 32.00086s32.00086-14.303454 32.00086-32.00086L545.982529 545.440667l317.087703-0.099772c0.063647 0 0.096331 0 0.127295 0 17.632039 0 31.935493-14.239806 32.00086-31.904529S880.960301 481.404542 863.328262 481.340895z" p-id="2248" fill="#ffffff"></path></svg>
</button>
<button style="padding: 10px;" class="el-button is-circle el-button--warning" @click="changeScale(-1)">
<svg t="1580884468915" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2481" width="16" height="16"><path d="M863.74455 544.00086 163.424056 544.00086c-17.664722 0-32.00086-14.336138-32.00086-32.00086s14.336138-32.00086 32.00086-32.00086l700.320495 0c17.695686 0 31.99914 14.336138 31.99914 32.00086S881.440237 544.00086 863.74455 544.00086z" p-id="2482" fill="#ffffff"></path></svg>
</button>
</div>
</div>
<div class="cropper-right">
<!--展示区域-->
<div class="show-preview">
<div :style="previews.div" class="preview">
<img :src="previews.url" :style="previews.img"/>
</div>
</div>
<!--按钮区域-->
<el-upload
class="upload-demo"
ref="upload"
action="https://jsonplaceholder.typicode.com/posts/"
:before-upload="beforeUpload"
:on-preview="handlePreview"
:on-remove="handleRemove"
:auto-upload="true"
:show-file-list="false"
>
<button class="el-button el-button--primary" slot="trigger" size="small" type="primary">选取图片</button>
<button class="el-button el-button--success" style="margin-left: 10px;" size="small" type="success" @click="submitUpload">上传头像</button>
<!-- <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div> -->
</el-upload>
</div>
</div>
</div>
</div>
</template>
<script>
import {VueCropper} from "vue-cropper";
import axios from 'axios';
export default {
name: 'tailoringUpload',
components: {
VueCropper
},
created(){
},
methods: {
submitUpload(file) {
window.console.log(file);
// this.$refs.upload.submit();
this.finish("blob");
},
handleRemove(file, fileList) {
window.console.log(file, fileList);
},
handlePreview(file) {
window.console.log(file);
// let data = window.URL.createObjectURL(new Blob([file]));
// this.option.img = data;
},
beforeUpload(file) {
window.console.log("上传文件");
window.console.log(file);
let data = window.URL.createObjectURL(new Blob([file]));
this.fileName = file.name;
this.option.img = data;
},
//放大/缩小
changeScale(num) {
window.console.log("changeScale");
num = num || 1;
this.$refs.cropper.changeScale(num);
},
//坐旋转
rotateLeft() {
window.console.log("rotateLeft");
this.$refs.cropper.rotateLeft();
},
//右旋转
rotateRight() {
window.console.log("rotateRight");
this.$refs.cropper.rotateRight();
},
//上传图片(点击上传按钮)
finish(type) {
let formData = new FormData();
// 输出
if (type === "blob") {
this.$refs.cropper.getCropBlob(data => {
let img = window.URL.createObjectURL(data);
this.model = true;
this.modelSrc = img;
formData.append("file", data, this.fileName);
this.http.post('file/upload-image', formData, {
headers: {'Access-Token': ''}
}).then(response => {
window.console.log("上传成功!", response);
if(response.status == 200){
var res = response.data;
if (res.status_code == 200) {
this.upload_status = '上传成功!';
}else{
this.upload_status = res.details.err_msg;
}
}else{
this.upload_status = '上传失败';
}
}).catch(function (error) {
window.console.log(error.response);
if (error.response) {
if(error.response.status == 401){
//登录失效的时候,跳转到登录页面
window.location.href="/dl?redirect="+window.location.pathname;
}else{
// 请求已发出,但服务器响应的状态码不在 2xx 范围内
this.upload_status = error.response.data;
}
} else {
window.console.log( "Error", error.message );
this.upload_status = error.message;
}
});
});
} else {
this.$refs.cropper.getCropData(data => {
this.model = true;
this.modelSrc = data;
});
}
},
// 实时预览函数
realTime(data) {
window.console.log("realTime");
this.previews = data;
},
imgLoad(msg) {
window.console.log("imgLoad");
window.console.log(msg);
}
},
data(){
return {
http: axios.create({
baseURL: 'https://xxx.upload.com/api/', //生产环境
withCredentials: false, //是否开启跨域,开启后可以设置自定义的header头,但是后端要开启*以及允许哪些header头
headers: {
// 'Content-Type':'multipart/form-data', //上传文件的时候,不用设置,会自动设置成 multipart/form-data
// 不能有拦截器,一旦添加拦截器,数据会自动变成Object,然后浏览器给出的是application/json,
},
}),
headImg: "",
//剪切图片上传
crap: false,
previews: {},
option: {
img: "",
outputSize: 1, //剪切后的图片质量(0.1-1)
full: false, //输出原图比例截图 props名full
outputType: "png",
canMove: true,
original: false,
canMoveBox: true,
autoCrop: true,
autoCropWidth: 150,
autoCropHeight: 150,
fixedBox: true
},
fileName: "", //本机文件地址
downImg: "#",
imgFile: "",
uploadImgRelaPath: "" //上传后的图片的地址(不带服务器域名)
}
}
}
</script>
<style scoped lang="less">
.certification-mask {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: rgba(85, 85, 85, 0.5);
vertical-align: middle;
z-index: 99999;
display: inline-grid;
display: flex;
.certification-box {
color: #222;
border-radius: 5px;
background-color: #fff;
/*width: 800px;*/
/*height: 480px;*/
margin: auto;
padding: 20px 50px;
position: relative;
.certification-top{
font-weight: bold;
height:45px;
line-height: 45px;
vertical-align: middle;
color:#222;
font-size: 16px;
border-bottom: 1px solid #F2F2F2;
text-align: center;
margin-bottom: 30px;
}
.certification-close {
width: 34px;
height: 34px;
position: absolute;
top: 0;
right: 0;
cursor: pointer;
img {
margin: 12px;
width: 10px;
height: 10px;
}
}
}
}
.cropper-content {
min-width: 540px;
/*display: flex;*/
/*border:1px solid blue;*/
// display: -webkit-flex;
// justify-content: flex-end;
// -webkit-justify-content: flex-end;
.cropper-left{
float: left;
width: 260px;
/*height:400px;*/
/*border: 1px solid olivedrab;*/
.cropper {
width: 260px;
height: 260px;
}
.cropper-operate{
margin: 20px auto;
button{
width:40px;
height:40px;
margin-right: 33px;
&:nth-of-type(4){
margin-right: 0;
}
}
}
}
.cropper-right{
margin-left:20px;
float: left;
.show-preview {
width: 150px;
height:155px;
overflow: hidden;
flex: 1;
-webkit-flex: 1;
display: flex;
display: -webkit-flex;
justify-content: center;
-webkit-justify-content: center;
margin: auto;
.preview {
overflow: hidden;
border-radius: 50%;
border: 1px solid #cccccc;
background: #cccccc;
width:150px !important;
height:150px !important;
}
}
.upload-demo{
margin:20px auto;
button{
height:40px;
padding:auto 5px;
}
}
}
}
.el-button {
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
background: #FFF;
border: 1px solid #DCDFE6;
color: #606266;
-webkit-appearance: none;
text-align: center;
-webkit-box-sizing: border-box;
box-sizing: border-box;
outline: 0;
margin: 0;
-webkit-transition: .1s;
transition: .1s;
font-weight: 500;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
padding: 12px 20px;
font-size: 14px;
border-radius: 4px;
}
.el-button.is-circle {
border-radius: 50%;
padding: 9px;
}
.el-button--primary {
color: #FFF;
background-color: #409EFF;
border-color: #409EFF;
}
.el-button--success {
color: #FFF;
background-color: #67C23A;
border-color: #67C23A;
}
.el-button--danger {
color: #FFF;
background-color: #F56C6C;
border-color: #F56C6C;
}
.el-button--warning {
color: #FFF;
background-color: #E6A23C;
border-color: #E6A23C;
}
.cropper-content .show-preview .preview {
margin-left: 0;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-khtml-user-select: none;
user-select: none;
}
</style>