<template>
<div>
<el-upload
ref="upload"
action
accept="video/*, image/*"
list-type="picture-card"
:before-upload="beforeUpload"
:http-request="handleUploadRequest"
:on-remove="handleRemove"
:on-exceed="handleExceed"
:on-preview="handlePreview"
:show-file-list="true"
:limit="limit"
:multiple="true"
:file-list="fileList"
>
<i class="el-icon-plus"></i>
</el-upload>
<!-- 视频播放弹框 -->
<el-dialog :visible.sync="showVideo" width="1000px" append-to-body>
<video
v-if="showVideo"
ref="video"
:src="videoSrc"
controls="controls"
width="100%"
height="500"
></video>
</el-dialog>
<!-- 图片预览器 -->
<el-image-viewer
v-if="showViewer"
:on-close="handleCloseViewer"
:url-list="viewList"
:z-index="3000"
/>
</div>
</template>
<script>
import client from "@/utils/ali-oss.js";
import ElImageViewer from "element-ui/packages/image/src/image-viewer";
// 上传视频,截取视频第一帧作为图片的文档:https://help.aliyun.com/document_detail/64555.html?spm=a2c4g.11186623.6.769.283a776bEOUKzW
export default {
name: "UploadImgAndVideo",
components: { ElImageViewer },
props: {
// 上传文件列表
fileList: {
type: Array,
default: () => {
return [];
},
},
imgSize: {
type: [String, Number],
default: 5,
},
videoSize: {
type: [String, Number],
default: 50,
},
},
data() {
return {
showViewer: false, // 展示图片浏览器
showVideo: false, // 展示视频播放器
videoSrc: null, // 视频播放路径
viewList: [], // 图片浏览列表
uploadType: null, // 动态限制上传类型;要么只能图片 or 视频
limit: 9,
};
},
methods: {
// 上传前
beforeUpload(file) {
// 因为此业务需要的是img & video两种类型,上传第一个文件时需要设置后续上传类型
// 不能在beforeUpload通过fileList[0]判断之前上传的类型,fileList是异步添加,此处的fileList还没添加上;
let { type, size } = file;
const M = size / 1024 / 1024;
if (![/^image/, /^video/].some((it) => it.test(type))) {
this.$message.warning("请上传视频或图片!");
return Promise.reject();
}
// 图片文件
if (/^image/.test(type)) {
this.limit = 9;
if (M > this.imgSize) {
this.$message.warning(`图片大小限制在${this.imgSize}M`);
return Promise.reject();
}
// 上传第1个文件时,设置后续文件相同类型
if (this.uploadType === null) {
this.uploadType = "image";
}
}
// 视频文件
if (/^video/.test(type)) {
if (M > this.videoSize) {
this.$message.warning(`视频大小限制在${this.videoSize}M`);
return Promise.reject();
}
// 这里只能限制第1次上传的数量,无法限制第一次选择了多个视频数量;
this.limit = 1;
// 所以这里需要再判断一下,已上传过一个视频;
if (this.uploadType !== null) {
this.$message.warning("只能上传1个视频!");
return Promise.reject();
} else {
// 还未上传过则设置后续上传类型;
this.uploadType === "video";
}
}
},
// 自定义上传方式
async handleUploadRequest(file) {
try {
let pathName =
new Date().getTime() +
"_" +
Math.floor(Math.random() * 1000000) +
"_" +
file.file.name;
let res = await client.put(pathName, file.file);
let temp = {
url: res.url,
pathName: pathName,
fileName: file.file.name,
type: file.file.type,
uid: file.file.uid,
};
if (/^video/.test(file.file.type)) {
let picturePath =
res.url +
"?x-oss-process=video/snapshot,t_1,f_jpg,w_0,h_0,m_fast";
// 这里的url是视频封面作为list-file列表小框的图片预览地址;videoUrl视频获取资源的地址;
temp.url = picturePath;
temp.videoUrl = res.url;
}
// 需要返回给后端上传成功后的ali-oss文件url地址;如普通上传可在on-change中接收成功的fileList;
this.$emit("change", [...this.fileList, temp]);
} catch (err) {
console.log(
`%c上传ali-oss文件失败 ${err}`,
"background: orange"
);
// 自定义上传失败不会触发on-error回调函数,采用abort方法终止文件在fileList列表小框中预览回显;
this.$refs.upload.abort();
}
},
// 删除上传图片; file当前删除文件,fileList删除后剩余的文件列表;
async handleRemove(file, fileList) {
try {
let currentFile = this.fileList.find(
(it) => it.uid === file.uid
);
// 剩余文件长度为0时,重置上传类型;
if (fileList.length === 0) {
this.uploadType = null;
}
// 本地先重置再删远程,避免远程删不成功阻塞,导致本地文件依然占据fileList文件列表中;
this.$emit("change", fileList);
// 远程没删成功和本地删除是两回事;
await client.delete(currentFile.pathName);
} catch (err) {
console.log(
`%c删除ali-oss远程文件失败 ${err}`,
"background: orange"
);
}
},
// 撤销操作 - 删除ali-oss服务器中上传的文件;
handleFileListLeft(fileList) {
return new Promise(async (resolve, reject) => {
try {
for (var i = 0; i < fileList.length; i++) {
var file = fileList[i];
await client.delete(file.pathName);
}
resolve();
} catch (err) {
reject(err);
}
});
},
// 限制上传多少个文件
handleExceed() {
this.$message.warning(`只能上传1个视频或9张图片!`);
},
// 点击预览
handlePreview(file) {
if (/^image/.test(file.type)) {
this.showViewer = true;
this.viewList = [file.url];
} else {
this.videoSrc = file.videoUrl;
this.showVideo = true;
}
},
// 图片预览关闭
handleCloseViewer() {
this.showViewer = false;
},
},
};
</script>
<style scoped lang="less">
.el-dialog {
.el-dialog__body {
height: 400px;
}
}
</style>
本文标题:elment-ui upload 自定义上传ali-oss视频或
本文链接:https://www.haomeiwen.com/subject/dtpxpdtx.html
网友评论