|
|
@@ -1,14 +1,16 @@ |
|
|
|
<template> |
|
|
|
<n-upload |
|
|
|
action="#" |
|
|
|
:max="limit" |
|
|
|
:file-list="fileList" |
|
|
|
:max="data.limit" |
|
|
|
:file-list="data.fileList" |
|
|
|
:default-upload="false" |
|
|
|
@before-upload="beforeUpload" |
|
|
|
@change="handleChange" |
|
|
|
> |
|
|
|
<n-button> |
|
|
|
<FileOutlined /> |
|
|
|
<n-icon> |
|
|
|
<FileOutlined /> |
|
|
|
</n-icon> |
|
|
|
选择文件 |
|
|
|
</n-button> |
|
|
|
</n-upload> |
|
|
@@ -19,234 +21,213 @@ |
|
|
|
style="margin-top: 16px" |
|
|
|
@click="handleUploadStart" |
|
|
|
> |
|
|
|
<UploadOutlined /> |
|
|
|
{{ '开始上传' }} |
|
|
|
<n-icon> |
|
|
|
<UploadOutlined /> |
|
|
|
</n-icon> |
|
|
|
开始上传 |
|
|
|
</n-button> --> |
|
|
|
</template> |
|
|
|
|
|
|
|
<script> |
|
|
|
<script setup name="UploadVod"> |
|
|
|
import { FileOutlined, UploadOutlined } from '@vicons/antd' |
|
|
|
import { getAuth, refreshAuth } from '@/api/common/upload.js' |
|
|
|
import { defineComponent, reactive, toRefs } from 'vue' |
|
|
|
|
|
|
|
export default defineComponent({ |
|
|
|
name: 'UploadVod', |
|
|
|
components: { FileOutlined, UploadOutlined }, |
|
|
|
props: { |
|
|
|
limit: { |
|
|
|
type: Number, |
|
|
|
default: 10 |
|
|
|
}, |
|
|
|
id: { |
|
|
|
type: Number, |
|
|
|
default: null |
|
|
|
}, |
|
|
|
autoUpload: { |
|
|
|
type: Boolean, |
|
|
|
default: false |
|
|
|
} |
|
|
|
import { reactive } from 'vue' |
|
|
|
|
|
|
|
const props = defineProps({ |
|
|
|
limit: { |
|
|
|
type: Number, |
|
|
|
default: 10 |
|
|
|
}, |
|
|
|
emits: ['uploadStatus'], |
|
|
|
setup(props, { emit }) { |
|
|
|
const data = reactive({ |
|
|
|
limit: props.limit, |
|
|
|
timeout: '', // 请求超时时间 |
|
|
|
partSize: '', // 分片大小 |
|
|
|
parallel: '', // 分片数 |
|
|
|
retryCount: '', // 失败重试次数 |
|
|
|
retryDuration: '', // 失败重试间隔 |
|
|
|
region: 'cn-shanghai', // 配置项 |
|
|
|
userId: '224202346013657350', // 阿里云帐号ID |
|
|
|
|
|
|
|
uploader: null, // 上传实例 |
|
|
|
fileList: [], // 上传的文件列表 |
|
|
|
uploadFile: [], // 选中的文件列表 |
|
|
|
readyFile: {}, // 准备上传的文件列表 |
|
|
|
uploaderObject: {}, // 上传的实例化对象列表 |
|
|
|
startUpload: false |
|
|
|
}) |
|
|
|
|
|
|
|
/** |
|
|
|
* @description: 校验文件是否合规 |
|
|
|
* @param {*} file |
|
|
|
* @return {*} |
|
|
|
*/ |
|
|
|
function beforeUpload({ file }) { |
|
|
|
if (!file.type.match('video.*')) { |
|
|
|
$message.error('请选择正确的视频') |
|
|
|
return false |
|
|
|
} else { |
|
|
|
const hasSelect = data.fileList.some((item) => item.name === file.name) |
|
|
|
if (hasSelect) { |
|
|
|
$message.error('您已选择过该文件') |
|
|
|
return false |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
/** |
|
|
|
* @description: 文件发生变化时,过滤不符合条件与重复的文件 |
|
|
|
* @param {Array} fileList |
|
|
|
* @return {*} |
|
|
|
*/ |
|
|
|
function handleChange({ fileList }) { |
|
|
|
data.fileList = fileList |
|
|
|
/* 若未实例化过,则实例化上传对象 */ |
|
|
|
if (!data.uploader) { |
|
|
|
data.uploader.createUploader() |
|
|
|
} |
|
|
|
const status = fileList.length ? 'ready' : 'no-file' |
|
|
|
emit('uploadStatus', { status }) |
|
|
|
autoUpload: { |
|
|
|
type: Boolean, |
|
|
|
default: false |
|
|
|
} |
|
|
|
}) |
|
|
|
const emit = defineEmits(['uploadStatus']) |
|
|
|
|
|
|
|
const data = reactive({ |
|
|
|
limit: props.limit, |
|
|
|
timeout: '', // 请求超时时间 |
|
|
|
partSize: '', // 分片大小 |
|
|
|
parallel: '', // 分片数 |
|
|
|
retryCount: '', // 失败重试次数 |
|
|
|
retryDuration: '', // 失败重试间隔 |
|
|
|
region: 'cn-shanghai', // 配置项 |
|
|
|
userId: '224202346013657350', // 阿里云帐号ID |
|
|
|
|
|
|
|
uploader: null, // 上传实例 |
|
|
|
fileList: [], // 上传的文件列表 |
|
|
|
uploadFile: [], // 选中的文件列表 |
|
|
|
readyFile: {}, // 准备上传的文件列表 |
|
|
|
uploaderObject: {} // 上传的实例化对象列表 |
|
|
|
}) |
|
|
|
|
|
|
|
/** |
|
|
|
* @description: 校验文件是否合规 |
|
|
|
* @param {*} file |
|
|
|
* @return {*} |
|
|
|
*/ |
|
|
|
const beforeUpload = ({ file }) => { |
|
|
|
if (!file.type.match('video.*')) { |
|
|
|
$message.error('请选择正确的视频') |
|
|
|
return false |
|
|
|
} else { |
|
|
|
const hasSelect = data.fileList.some((item) => item.name === file.name) |
|
|
|
if (!hasSelect) { |
|
|
|
data.uploadFile.push(file.file) |
|
|
|
} else { |
|
|
|
$message.error('您已选择过该文件') |
|
|
|
return false |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @description: 开始上传文件 |
|
|
|
* @param {*} |
|
|
|
* @return {*} |
|
|
|
*/ |
|
|
|
function handleUploadStart() { |
|
|
|
if (data.uploader !== null) { |
|
|
|
data.startUpload = true |
|
|
|
data.uploader.startUpload() |
|
|
|
/** |
|
|
|
* @description: 文件发生变化时,过滤不符合条件与重复的文件 |
|
|
|
* @param {Array} fileList |
|
|
|
* @return {*} |
|
|
|
*/ |
|
|
|
const handleChange = ({ fileList }) => { |
|
|
|
data.fileList = fileList |
|
|
|
/* 若未实例化过,则实例化上传对象 */ |
|
|
|
if (!data.uploader) { |
|
|
|
data.uploader = createUploader() |
|
|
|
} |
|
|
|
const status = fileList.length ? 'ready' : 'no-file' |
|
|
|
emit('uploadStatus', { status, list: data.readyFile }) |
|
|
|
handleUploadReady() // 准备上传文件 |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @description: 创建上传的实例化对象 |
|
|
|
* @param {*} |
|
|
|
* @return {*} |
|
|
|
*/ |
|
|
|
const createUploader = () => { |
|
|
|
const uploader = new AliyunUpload.Vod({ |
|
|
|
timeout: data.timeout || 60000, |
|
|
|
partSize: data.partSize || 1048576, |
|
|
|
parallel: data.parallel || 5, |
|
|
|
retryCount: data.retryCount || 3, |
|
|
|
retryDuration: data.retryDuration || 2, |
|
|
|
region: data.region, |
|
|
|
userId: data.userId, |
|
|
|
/* 添加文件成功 */ |
|
|
|
addFileSuccess: function(uploadInfo) { |
|
|
|
// console.log('addFileSuccess: ' + uploadInfo.file.name) |
|
|
|
}, |
|
|
|
// 开始上传 |
|
|
|
onUploadstarted: function(uploadInfo) { |
|
|
|
console.log('uploader', uploader) |
|
|
|
if (uploadInfo.videoId) { |
|
|
|
// 如果uploadInfo.videoId存在,调用刷新视频上传凭证接口 |
|
|
|
refreshAuth(uploadInfo.videoId).then(res => { |
|
|
|
uploader.setUploadAuthAndAddress(uploadInfo, res.data.uploadAuth, res.data.uploadAddress, res.data.videoId) |
|
|
|
}) |
|
|
|
} else { |
|
|
|
createUploader() |
|
|
|
const params = { |
|
|
|
title: uploadInfo.file.name, |
|
|
|
fileName: uploadInfo.file.name |
|
|
|
} |
|
|
|
getAuth(params).then(res => { |
|
|
|
uploader.setUploadAuthAndAddress(uploadInfo, res.data.uploadAuth, res.data.uploadAddress, res.data.videoId) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
/** |
|
|
|
* @description: 添加文件到实例对象中 |
|
|
|
* @param {*} |
|
|
|
* @return {*} |
|
|
|
*/ |
|
|
|
function handleUploadReady() { |
|
|
|
data.fileList.forEach((item, index) => { |
|
|
|
/* 是否已经添加过该文件 */ |
|
|
|
if (!Object.keys(data.readyFile).includes(item.id)) { |
|
|
|
const obj = { |
|
|
|
name: item.name, |
|
|
|
url: '' |
|
|
|
} |
|
|
|
data.readyFile[item.id] = obj |
|
|
|
data.uploader.addFile(item, null, null, null, '{"Vod":{}}') |
|
|
|
}, |
|
|
|
|
|
|
|
// 文件上传成功 |
|
|
|
onUploadSucceed: function(uploadInfo) { |
|
|
|
const fileName = uploadInfo.file.name |
|
|
|
data.fileList.forEach((item) => { |
|
|
|
if (item.name === fileName) { |
|
|
|
console.log('readyFile', data.readyFile) |
|
|
|
data.readyFile[item.uid].url = uploadInfo.object |
|
|
|
} |
|
|
|
}) |
|
|
|
data.uploader.startUpload() |
|
|
|
} |
|
|
|
}, |
|
|
|
// 文件上传失败 |
|
|
|
onUploadFailed: function(uploadInfo, code, message) { |
|
|
|
console.log('onUploadFailed: file:' + uploadInfo.file.name + ',code:' + code + ', message:' + message) |
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
* @description: 创建上传的实例化对象 |
|
|
|
* @param {*} |
|
|
|
* @return {*} |
|
|
|
*/ |
|
|
|
function createUploader() { |
|
|
|
const uploader = new AliyunUpload.Vod({ |
|
|
|
timeout: data.timeout || 60000, |
|
|
|
partSize: data.partSize || 1048576, |
|
|
|
parallel: data.parallel || 5, |
|
|
|
retryCount: data.retryCount || 3, |
|
|
|
retryDuration: data.retryDuration || 2, |
|
|
|
region: data.region, |
|
|
|
userId: data.userId, |
|
|
|
/* 添加文件成功 */ |
|
|
|
addFileSuccess: function(uploadInfo) { |
|
|
|
// console.log('addFileSuccess: ' + uploadInfo.file.name) |
|
|
|
}, |
|
|
|
// 开始上传 |
|
|
|
onUploadstarted: function(uploadInfo) { |
|
|
|
if (uploadInfo.videoId) { |
|
|
|
// 如果uploadInfo.videoId存在,调用刷新视频上传凭证接口 |
|
|
|
refreshAuth(uploadInfo.videoId) |
|
|
|
.then(res => { |
|
|
|
uploader.setUploadAuthAndAddress(uploadInfo, res.data.uploadAuth, res.data.uploadAddress, res.data.videoId) |
|
|
|
}) |
|
|
|
} else { |
|
|
|
const params = { |
|
|
|
title: uploadInfo.file.name, |
|
|
|
fileName: uploadInfo.file.name |
|
|
|
} |
|
|
|
getAuth(params) |
|
|
|
.then(res => { |
|
|
|
uploader.setUploadAuthAndAddress(uploadInfo, res.data.uploadAuth, res.data.uploadAddress, res.data.videoId) |
|
|
|
}) |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
// 文件上传成功 |
|
|
|
onUploadSucceed: function(uploadInfo) { |
|
|
|
const fileName = uploadInfo.file.name |
|
|
|
data.fileList.forEach((item) => { |
|
|
|
if (item.name === fileName) { |
|
|
|
data.readyFile[item.uid].url = uploadInfo.object |
|
|
|
} |
|
|
|
}) |
|
|
|
}, |
|
|
|
// 文件上传失败 |
|
|
|
onUploadFailed: function(uploadInfo, code, message) { |
|
|
|
// console.log('onUploadFailed: file:' + uploadInfo.file.name + ',code:' + code + ', message:' + message) |
|
|
|
}, |
|
|
|
|
|
|
|
// 取消文件上传 |
|
|
|
onUploadCanceled: function(uploadInfo, code, message) { |
|
|
|
// console.log('Canceled file: ' + uploadInfo.file.name + ', code: ' + code + ', message:' + message) |
|
|
|
}, |
|
|
|
|
|
|
|
// 文件上传进度,单位:字节, 可以在这个函数中拿到上传进度并显示在页面上 |
|
|
|
onUploadProgress: function(uploadInfo, totalSize, progress) { |
|
|
|
// console.log("onUploadProgress:file:" + uploadInfo.file.name + ", fileSize:" + totalSize + ", percent:" + Math.ceil(progress * 100) + "%") |
|
|
|
const progressPercent = Math.ceil(progress * 100) |
|
|
|
const fileName = uploadInfo.file.name |
|
|
|
data.fileList.forEach((item) => { |
|
|
|
if (item.name === fileName) { |
|
|
|
item.status = progressPercent === 100 ? 'success' : 'uploading' |
|
|
|
item.percent = progressPercent |
|
|
|
} |
|
|
|
}) |
|
|
|
}, |
|
|
|
|
|
|
|
// 上传凭证超时 |
|
|
|
onUploadTokenExpired: function(uploadInfo) { |
|
|
|
refreshAuth(uploadInfo.videoId) |
|
|
|
.then(res => { |
|
|
|
uploader.resumeUploadWithAuth(uploadInfo, res.data.uploadAuth, res.data.uploadAddress, res.data.videoId) |
|
|
|
}) |
|
|
|
}, |
|
|
|
|
|
|
|
// 全部文件上传结束 |
|
|
|
onUploadEnd: function(uploadInfo) { |
|
|
|
// console.log('onUploadEnd: uploaded all the files', uploadInfo) |
|
|
|
emit('uploadStatus', { status: 'success', list: data.readyFile }) |
|
|
|
// 取消文件上传 |
|
|
|
onUploadCanceled: function(uploadInfo, code, message) { |
|
|
|
// console.log('Canceled file: ' + uploadInfo.file.name + ', code: ' + code + ', message:' + message) |
|
|
|
}, |
|
|
|
|
|
|
|
// 文件上传进度,单位:字节, 可以在这个函数中拿到上传进度并显示在页面上 |
|
|
|
onUploadProgress: function(uploadInfo, totalSize, progress) { |
|
|
|
// console.log("onUploadProgress:file:" + uploadInfo.file.name + ", fileSize:" + totalSize + ", percent:" + Math.ceil(progress * 100) + "%") |
|
|
|
const progressPercent = Math.ceil(progress * 100) |
|
|
|
const fileName = uploadInfo.file.name |
|
|
|
data.fileList.forEach((item) => { |
|
|
|
if (item.name === fileName) { |
|
|
|
item.status = progressPercent === 100 ? 'success' : 'uploading' |
|
|
|
item.percent = progressPercent |
|
|
|
} |
|
|
|
}) |
|
|
|
return uploader |
|
|
|
}, |
|
|
|
|
|
|
|
// 上传凭证超时 |
|
|
|
onUploadTokenExpired: function(uploadInfo) { |
|
|
|
console.log('onUploadTokenExpired', uploadInfo) |
|
|
|
refreshAuth(uploadInfo.videoId).then(res => { |
|
|
|
uploader.resumeUploadWithAuth(uploadInfo, res.data.uploadAuth, res.data.uploadAddress, res.data.videoId) |
|
|
|
}) |
|
|
|
}, |
|
|
|
|
|
|
|
// 全部文件上传结束 |
|
|
|
onUploadEnd: function(uploadInfo) { |
|
|
|
// console.log('onUploadEnd: uploaded all the files', uploadInfo) |
|
|
|
emit('uploadStatus', { status: 'success', list: data.readyFile }) |
|
|
|
} |
|
|
|
}) |
|
|
|
return uploader |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @description: 暂停上传 |
|
|
|
* @param {*} |
|
|
|
* @return {*} |
|
|
|
*/ |
|
|
|
function handleUploadStop() { |
|
|
|
if (data.uploader !== null) { |
|
|
|
data.startUpload = false |
|
|
|
data.uploader.stopUpload() |
|
|
|
/** |
|
|
|
* @description: 新建文件到实例对象中 |
|
|
|
* @param {*} |
|
|
|
* @return {*} |
|
|
|
*/ |
|
|
|
const handleUploadReady = () => { |
|
|
|
data.uploadFile.forEach((item, index) => { |
|
|
|
/* 是否已经新建过该文件 */ |
|
|
|
if (!Object.keys(data.readyFile).includes(item.uid)) { |
|
|
|
const obj = { |
|
|
|
name: item.name, |
|
|
|
url: '' |
|
|
|
} |
|
|
|
data.readyFile[item.uid] = obj |
|
|
|
data.uploader.addFile(item, null, null, null, '{"Vod":{}}') |
|
|
|
} |
|
|
|
}) |
|
|
|
// if (props.autoUpload) { // 判断是否自动上传 |
|
|
|
// handleUploadStart() |
|
|
|
// } |
|
|
|
handleUploadStart() |
|
|
|
} |
|
|
|
|
|
|
|
return { |
|
|
|
...toRefs(data), |
|
|
|
beforeUpload, |
|
|
|
handleChange, |
|
|
|
handleUploadStart, |
|
|
|
handleUploadStop |
|
|
|
} |
|
|
|
/** |
|
|
|
* @description: 开始上传文件 |
|
|
|
* @param {*} |
|
|
|
* @return {*} |
|
|
|
*/ |
|
|
|
const handleUploadStart = () => { |
|
|
|
if (data.uploader !== null) { |
|
|
|
data.uploader.startUpload() |
|
|
|
emit('uploadStatus', { status: 'uploading', list: data.readyFile }) |
|
|
|
} |
|
|
|
}) |
|
|
|
} |
|
|
|
</script> |
|
|
|
|
|
|
|
<style lang="scss" scoped> |
|
|
|
.upload{ |
|
|
|
.upload { |
|
|
|
list-style: none; |
|
|
|
padding: 10px 20px; |
|
|
|
} |
|
|
|
.upload .upload-item__name{ |
|
|
|
|
|
|
|
.upload .upload-item__name { |
|
|
|
margin-bottom: 5px; |
|
|
|
} |
|
|
|
</style> |