和vue组件一样引用就行
<Upload
:action="action"
:headers="headers"
@onSuccess="handleUploadSuccess"
@onError="handleUploadError"
@onRemove="hanldeRemoveIcon"
@onBeforeUpload="beforeUploadImage"
:image-url="formData.imageUrl"
:tip-text="$t('emp_max_10m')"
></Upload>
mixins.js
export default {

props: {
icon: {
//上传组件的占位图
type: String,
default: 'iconcamera'
},
size: {
//图片超过指定大小不让上传
type: Number,
default: 30720
},
disabled: {
//禁止上传
type: Boolean
},
iconSize: {
//占位icon的大小
type: Number,
default: 24
},
name: {
//input的原生属性
type: String,
default: 'file'
},
accept: {
//接受上传的文件类型
type: Array,
default() {
return []
}
},
acceptErrorMessage: {
//文件类型错误的提示内容
type: String,
default: '文件类型错误'
},
compress: {
//是否开启图片压缩
type: Boolean,
default: true
},
compressSize: {
//超过大小的图片压缩
type: Number,
default: 512
},
data: {
//上传附带的内容
type: Object,
default() {
return {}
}
},
action: {
//上传地址
type: String,
default: ''
},
headers: {
//设置上传的请求头部
type: Object,
default() {
return {}
}
},
imgWidth: {
//图片压缩时指定压缩的图片宽度
type: [Number, Boolean],
default: 800
},
quality: {
//图片压缩的质量
type: Number,
default: 1
},
beforeUpload: {
//上传文件之前的钩子
type: Function
},
onSuccess: {
//上传成功的钩子
type: Function
},
onError: {
//上传失败的钩子
type: Function
},
onLoadend: {
//文件上传成功或者失败都会执行的钩子
type: Function
},
onProgress: {
//文件上传进度的钩子
type: Function
},
onSuccessText: {
//上传成功的提示内容
type: String,
default: '上传成功'
},
onErrorText: {
//上传失败的提示内容
type: String,
default: '上传失败'
},
beforeRemove: {
//删除文件的钩子
type: Function
},
showRemove: {
//是否展示删除icon
type: Boolean,
default: true
},
type: {
//单文件上传还是多文件上传
type: String,
default: 'single',
validator: function (value) {
return ['single', 'multiple'].includes(value)
}
},
maxNumber: {
//多文件上传最多上传的个数
type: Number
},
isImage: {
//文件是否为图片
type: Boolean,
}
}
}
upload.vue
<!-- components/upload.vue -->
<template>
<div class="g7-Upload-single">
<div class="g7-Upload-default-icon">
<template v-if="!value">
<slot>
<!-- <Icon :size="iconSize" :icon="icon" /> -->
<i class="el-icon-upload" />
</slot>
</template>
<template v-else>
<template v-if="isImage">
<img class="g7-Upload-img" :src="value" />
</template>
<template v-else>
<!-- <Icon :size="34" icon="iconicon-" /> -->
<i class="el-icon-upload" />
</template>
<span
@click.stop="onRemove"
v-if="showRemove"
class="g7-Upload-removeImg"
>
<!-- <Icon :size="14" icon="iconcuowu" color="#fff" /> -->
<i class="el-icon-upload" />
</span>
</template>
</div>
<input
class="g7-Upload-input"
@change="change"
:disabled="computedDisabled"
:name="name"
type="file"
ref="input"
/>
<!-- 图片压缩需要用到的canvas -->
<canvas hidden="hidden" v-if="compress" ref="canvas"></canvas>
<!-- 进度条 -->
<div v-if="progress > 0" class="g7-Upload-progress">
<div
:style="{ width: `${progress}%` }"
class="g7-Upload-progress-bar"
></div>
</div>
</div>
</template>
<script>
// import Icon from './Icon' //自定义组件
import mixins from './mixins'
import { getType, fetch } from './utils'
// import Toast from '../../~Toast' //自定义组件
const compressList = ['png', 'PNG', 'jpg', 'JPG', 'jpeg', 'JPEG']
export default {
// components: { Icon },
mixins: [mixins],
props: {
value: {
type: String
}
},
data() {
return {
file: '',
progress: 0,
src: ''
}
},
computed: {
computedDisabled() {
return this.disabled || this.progress !== 0
}
},
methods: {
change(e) {
if (this.disabled) {
return
}
// debugger
const file = e.target.files[0]
console.log('log--> eeeee', e.target.files)
console.log('log--> file', file)
if (!file) {
return
}
const type = getType(file.name)
if (this.accept.length) {
if (!this.accept.includes(type)) {
this.$message.info(this.acceptErrorMessage)
return
}
}
const size = Math.round((file.size / 1024) * 100) / 100
if (size > this.size) {
this.$message.info(`请上传小于${this.size / 1024}M的文件`)
return
}
// if (this.isCompress(type, size)) {
// console.log('log--> URL', URL)
// this.canvasDataURL(URL.createObjectURL(file))
// return
// }
this.$emit('on-change')
this.file = file
this.upload(file)
},
// /**
// * 判断是否满足压缩条件
// */
// isCompress(type, size) {
// console.log(
// 'log-->this.compress ',
// this.compress,
// compressList.includes(type),
// size,
// this.compressSize
// )
// return (
// this.compress && compressList.includes(type) && size > this.compressSize
// )
// },
// canvasDataURL(base) {
// const img = new Image()
// img.src = base
// const that = this
// function ImgOnload() {
// /**
// * 计算生成图片的宽高
// */
// const scale = this.width / this.height
// const width =
// that.imgWidth === false || this.width <= that.imgWidth
// ? this.width
// : that.imgWidth
// const height = width / scale
// const canvas = that.$refs.canvas
// canvas.width = width
// canvas.height = height
// // 利用canvas绘制压缩的图片并生成新的blob
// const context = canvas.getContext('2d')
// context.drawImage(this, 0, 0, width, height)
// canvas.toBlob(
// (blob) => {
// that.file = blob
// that.upload(blob)
// that.$emit('on-change', blob, that.options)
// },
// 'image/png',
// that.quality
// )
// /**
// * 使用完的createObjectURL需要释放内存
// */
// window.URL.revokeObjectURL(this.src)
// }
// img.onload = ImgOnload
// },
/**
* 上传成功
*/
onload(e) {
this.progress = 0
this.$emit('input', e)
if (this.onSuccess) {
this.onSuccess(this.file, e)
return
}
this.$message.info(this.onSuccessText)
},
/**
* 上传进度
*/
uploadProgress(e) {
this.progress = e.percent
console.log('log--> e.percent', e.percent)
if (this.onProgress < 100) {
this.onProgress(this.file, e)
}
},
/**
* 上传失败
*/
uploadError(e) {
this.progress = 0
if (this.onError) {
this.onSuccess(this.file, e)
return
}
this.$message.info(this.onErrorText)
},
/**
* 请求结束
*/
uploadLoadend(e) {
this.clearInput()
if (this.onloadend) {
this.onloadend(this.file, e)
}
},
/**
* 上传
*/
upload(file) {
// this.clearInput()
if (!this.beforeUpload) {
fetch(this, file)
return
}
const before = this.beforeUpload(file)
if (before && before.then) {
before.then((res) => {
if (res !== false) {
fetch(this, file)
}
})
return
}
if (before !== false) {
fetch(this, file)
}
},
/**
* 删除文件
*/
onRemove() {
// this.clearInput()
if (this.type === 'single') {
if (!this.beforeRemove) {
this.$emit('input', '')
return
}
const before = this.beforeRemove(this.file, this.value)
if (before && before.then) {
before.then((res) => {
if (res !== false) {
this.$emit('input', '')
}
})
return
}
if (before !== false) {
this.$emit('input', '')
}
return
}
this.$emit('on-remove')
},
clearInput() {
this.$refs.input.value = null
}
}
}
</script>
uploadExport.vue
<template>
<div class="g7-Upload">
<template v-if="type === 'single'">
<Upload
ref="upload"
:icon="icon"
:size="size"
:accept="accept"
:name="name"
:acceptErrorMessage="acceptErrorMessage"
:compress="compress"
:iconSize="iconSize"
:compressSize="compressSize"
:imgWidth="imgWidth"
:headers="headers"
:action="action"
:data="data"
:quality="quality"
:beforeRemove="beforeRemove"
:beforeUpload="beforeUpload"
:onSuccess="onSuccess"
:onSuccessText="onSuccessText"
:onError="onError"
:onProgress="onProgressFun"
:onLoadend="onLoadend"
:onErrorText="onErrorText"
:disabled="disabled"
:showRemove="showRemove"
v-model="currentValue"
@input="input"
:type="type"
:maxNumber="maxNumber"
:isImage="isImage"
>
<slot></slot>
</Upload>
</template>
</div>
</template>
<script>
import Upload from './upload'
import mixins from './mixins'
export default {
name: 'GUpload',
components: { Upload },
mixins: [mixins],
props: {
// eslint-disable-next-line vue/require-default-prop
value: {
type: [String, Array]
}
},
data() {
return {
currentValue: this.value
}
},
watch: {
value(val) {
this.currentValue = val
}
},
methods: {
input(val) {
this.$emit('input', val)
},
// 接管文件上传时,自定义文件上传进度
onProgressFun(percent) {
this.$refs.upload.uploadProgress(percent)
}
}
}
</script>
utils.js
/**
* 获取文件的后缀
* @param {*} file
*/
export const getType = (file) => file.substr(file.lastIndexOf('.') + 1)
/**
* 请求封装
* @param {*} options
* @param {*} file
*/
export function fetch(options, file) {
// console.log('log--> ', typeof XMLHttpRequest)
if (typeof XMLHttpRequest === 'undefined') {
return
}
const xhr = new XMLHttpRequest()
console.log('log--> xhr', xhr)
const action = options.action
if (xhr.upload) {
xhr.upload.onprogress = function progress(e) {
if (e.total > 0) {
e.percent = (e.loaded / e.total) * 100
}
options.uploadProgress(e)
}
}
const formData = new FormData()
console.log('log--> formData', formData)
formData.append(options.name, file, options.fileName)
for (const key in options.data) {
formData.append(key, options.data[key])
}
// 成功回调
xhr.onload = (e) => {
console.log('log-->成功回调 e', e)
console.log('log-->成功回调e.target.response ', e.target.response)
const response = e.target.response
if (xhr.status < 200 || xhr.status >= 300) {
options.uploadError(response)
return
}
options.onload(response)
}
// 出错回调
xhr.onerror = (e) => {
const response = e.target.response
options.uploadError(response)
}
// 请求结束
xhr.onloadend = (e) => {
const response = e.target.response
options.uploadLoadend(response)
}
xhr.open('post', action, true)
const headers = options.headers
for (const key in headers) {
if (headers[key] !== null) {
xhr.setRequestHeader(key, headers[key])
}
}
console.log('log--> formData2', formData)
xhr.send(formData)
}