第一步,封装js文件在util文件下:
// fileUpload.js
import axios from 'axios'
let basePath = 'xxx.xxx.xx' // 你的服务器接口域名
/**
* @description: 文件附件上传
* file: 文件raw对象
* successCallback: 成功的回调函数
* errCallBack: 错误的回调函数
* progressCallback: 上传进度的回调函数
* dir: 上传阿里云目标文件夹 eg:图片image,视频video等
*/
const upload = function(file, successCallback = new Function(), errCallBack = new Function(), progressCallback = new Function(), dir = 'image') {
let fileName = file.name
axios({
method: 'get',
url: "www.wwww.www" // 请求签名接口,找后台要
})
.then(res => {
// 拿到签名信息后,组装表单数据,作参考,具体的字段找后台要
let obj = res.data
let config = {}
config.host = obj['host']
config.policyBase64 = obj['policy']
config.accessid = obj['accessid']
config.signature = obj['signature']
config.expire = parseInt(obj['expire'])
config.callbackbody = obj['callback']
config.dir = obj['dir']
let fd = new FormData(),
key = config.dir + fileName //文件名
fd.append('key', key)
fd.append('success_action_status', '200')
fd.append('x-oss-object-acl', 'public-read')
fd.append('x-oss-meta-fullname', fileName)
fd.append('OSSAccessKeyId', config.accessid)
fd.append('policy', config.policyBase64)
fd.append('signature', config.signature)
fd.append('success_action_status', '200')
fd.append('file', file)
if (config.host.indexOf('http:') > -1) {
var protocol = window.location.protocol || 'http:'
var subUrl = config.host.substring(5, config.host.length)
config.host = protocol + subUrl
}
// 数据组装完成后,发送上传请求到阿里云oss
axios({
url: config.host,
method: 'POST',
data: fd,
processData: false,
cache: false,
contentType: false,
// 这里,我们可以做上传经度
onUploadProgress: function(progressEvent) {
if (progressEvent.lengthComputable) {
let percent = (progressEvent.loaded / progressEvent.total) * 100 || 0
progressCallback({
percent: percent
})
}
}
})
.then(() => {
// 拿到结果后,做其他操作
let size = file.size > 1000000 ? parseFloat(file.size / 1000000).toFixed(2) + 'M' : parseFloat(file.size / 1000).toFixed(2) + 'KB'
successCallback({
attachment: fileName,
aliyunAddress: key,
size: size,
host: config.host
})
})
.catch(err => {
errCallBack(err)
})
})
.catch(err => {
errCallBack(err)
})
}
export default upload
第二部,将el-upload的组件结合封装
<template>
<div class="text-msg-pic-upload flex-start">
<div v-if="Filetype=='video'">
<video v-for="i in tempFileList" :key="i.uid" :src="i.url" width="96" height="96" class="video" @click="handlePictureCardPreview_video(i)"></video>
</div>
<el-upload
:class="{ display: uploadDisabled }"
list-type="picture-card"
ref="upload"
action
multiple
:http-request="handleUpload"
:auto-upload="autoUpload"
:limit="limit"
:file-list="tempFileList"
:on-exceed="handleExceed"
:on-success="handleSuccess"
:on-remove="handleRemove"
:before-remove="beforeRemove"
:before-upload="beforeUpload"
:on-preview="handlePictureCardPreview"
:show-file-list="Filetype=='image'"
accept="jpg,.jpeg,.png,.JPG,.JPEG,.mp4,.wmv,.rmvb,.mov,.avi,.flv"
>
<i class="el-icon-plus"></i>
<div slot="tip" class="el-upload__tip" v-if="tipsFlag">{{ tips }}</div>
</el-upload>
<el-dialog :visible.sync="dialogVisible" append-to-body @close="closeDialog">
<img width="100%" :src="dialogImageUrl" alt="" />
</el-dialog>
<el-dialog :visible.sync="dialogVisible_video" append-to-body @close="closeDialog">
<video width="100%" :src="dialogVideoUrl" controls/>
</el-dialog>
</div>
</template>
<script>
import upload from '@/utils/fileUpload.js'
export default {
// name: 'UploadImageDemo',
props: {
width: {
type: String,
default: '240px'
},
Filetype: {
type: String,
default: 'image'
},
size: {
type: String,
default: 50
},
autoUpload: {
type: Boolean,
default: true
},
limit: {
type: Number,
default: 3
},
limitType: {
type: Array,
default: () => ['image/jpeg', 'image/png', 'image/jpg']
},
disabled: {
type: Boolean,
default: false
},
imgList: {
type: Array,
default: () => []
},
tipsFlag: {
type: Boolean,
default: false
},
tips: {
type: String,
default: ''
}
},
data() {
return {
// 上传文件列表,el-upload使用,临时保存数据。
tempFileList: this.imgList,
host: '', // 阿里云上传服务器地址根路径
uploadDisabled: false,
dialogImageUrl: '',
dialogVisible: false,
dialogVisible_video:false,
dialogVideoUrl:'',
}
},
watch: {
// 解决第二渲染接口, 图片还保留着原来的问题 JerryYi
imgList: {
immediate: true,
handler(val) {
this.tempFileList = val
}
}
},
computed: {
upText() {
return this.autoUpload ? '上传文件' : '选择文件'
}
},
created() {
},
mounted() {},
methods: {
handlePictureCardPreview_video(file) {
this.dialogVideoUrl = file.url
this.dialogVisible_video = true
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file.url
this.dialogVisible = true
},
closeDialog(){
this.dialogVideoUrl = ''
this.dialogImageUrl = ''
this.dialogVisible_video = false
this.dialogVisible = false
},
beforeUpload(file) {
let types = this.limitType
const isImage = types.includes(file.type)
const isLt20M = file.size / 1024 / 1024 < parseInt(this.size)
if (!isImage) {
if(this.Filetype=='video'){
this.$message({
message: types.length == 0 ? '只能上传视频格式!' : '上传视频只能是 mp4、wmv、rmvb、mov、avi、flv 格式!',
type: 'warning'
})
return false
}
this.$message({
message: types.length == 0 ? '上传图片只能是 PNG 格式!' : '上传图片只能是 JPG、PNG 格式!',
type: 'warning'
})
return false
}
if (!isLt20M) {
this.$message.error('上传图片大小不能超过 '+parseInt(this.size)/10+'MB!')
return false
}
return isImage && isLt20M
},
// 自定义上传操作
handleUpload(op) {
let dir = `images`
upload(
op.file,
res => {
let temp = {
name: res.attachment,
url: res.host + '/' + res.aliyunAddress
}
this.host = res.host
op.onSuccess(temp)
},
err => {
console.log(err)
},
res => {
op.onProgress(res)
},
dir
)
},
// 上传成功后触发
handleSuccess(response, file, fileList) {
this.filterFileFn(fileList)
},
// 返回给接口要用的格式
filterFileFn(fileList) {
let filterArr = fileList
.filter(item => !item.status || item.status !== 'ready') // 过滤未上传的文件
.map(item => {
let url = item.response ? item.response.url : item.url
return {
url: url, // item.url || item.response.url
name: item.name
}
})
// console.log('fileList', fileList)
this.$emit('onSuccessFiles', filterArr)
},
// 监听移除文件列表
handleRemove(file, fileList) {
if (file.status === 'success') {
this.filterFileFn(fileList)
}
},
handleExceed(files, fileList) {
this.$message({ message: `当前限制选择 ${this.limit} 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`, type: 'warning' })
},
beforeRemove() {
// return this.$confirm(`确定移除 ${file.name}?`)
}
}
}
</script>
<style>
.text-msg-pic-upload .el-upload--picture-card,
.text-msg-pic-upload .el-upload-list--picture-card .el-upload-list__item {
width: 96px;
height: 96px;
line-height: 106px;
}
.display .el-upload--picture-card {
display: none;
}
.text-msg-pic-upload .video{
background-color: #fff;
cursor: pointer;
margin-right: 8px;
}
</style>
第三步,需要的地方就行引用
<template>
<--上传图片-->
<uploadImage :limit="5" :imgList="fileImgList" @onSuccessFiles="onSuccessImgFiles" />
<--上传视频-->
<uploadImage :limit="1" :imgList="fileImgList" @onSuccessFiles="onSuccessImgFiles" :limitType="limitType" size='200' Filetype='video' />
</template>
<script>
import uploadImage from './components/uploadImage'
export default {
components: {
uploadImage,
},
data () {
return {
fileImgList: [], //图片列表,
limitType:[
"video/mp4",
"video/ogg",
"video/flv",
"video/avi",
"video/wmv",
"video/rmvb",
"video/mov"]
}
},
methods: {
// 监听图片上传
onSuccessImgFiles(files) {
console.log('onSuccessImgFiles', files)
this.fileImgList = files
},
}
</script>
<style lang="scss">
@import "@/assets/scss/settings/feedback.scss";
</style>
可以看下详细:https://blog.csdn.net/qq_42991509/article/details/122967392