结合el-upload修改支持上传图片、视频并预览

结合element plus的el-upload标签,实现上传图片和视频,并支持在线预览和放大
1、html部分

<el-form-item label="活动照片、视频">
	<el-upload
		v-model:file-list="state.photoList"
		:action="state.uploadUrl"
		accept=".jpg,.png,.jpeg,.mp4,.mov,.avi"
		list-type="picture-card"
		:limit="10"
		:on-success="handleUpload"
		:class="state.photoList.length === 10 ? 'hideUpload' : ''">
		<el-icon><Plus /></el-icon>
		<template #file="{ file }">
			<div>
				<img
					v-if="file.name.indexOf('.jpg') > -1
						|| file.name.indexOf('.png') > -1
						|| file.name.indexOf('.jpeg') > -1"
					:src="file.url"
					alt=""
					class="el-upload-list__item-thumbnail" />
				<video
					v-else-if="file.name.indexOf('.mp4') > -1
						|| file.name.indexOf('.mov') > -1
						|| file.name.indexOf('.avi') > -1"
					class="el-upload-list__item-thumbnail"
					style="width: 100%;height: 100%;"
					autoplay
					:src="file.url">
					<source :src="file.url" type="video/mp4" />
					<source :src="file.url" type="video/mov" />
					<source :src="file.url" type="video/avi" />
				</video>
				<span class="el-upload-list__item-actions">
					<span class="el-upload-list__item-preview" @click="handlePreview(file)">
						<el-icon><zoom-in /></el-icon>
					</span>
					<span
						v-if="!state.disabledBtn"
						class="el-upload-list__item-delete"
						@click="handleRemove(file)">
						<el-icon><Delete /></el-icon>
					</span>
				</span>
			</div>
		</template>
	</el-upload>
	<el-dialog v-model="state.dialogVisible">
		<img
			w-full
			:src="state.dialogImageFile.url"
			alt=""
			v-if="state.dialogImageFile.name.indexOf('.jpg') > -1
				|| state.dialogImageFile.name.indexOf('.png') > -1
				|| state.dialogImageFile.name.indexOf('.jpeg') > -1" />
		<video
			v-else-if="state.dialogImageFile.name.indexOf('.mp4') > -1
				|| state.dialogImageFile.name.indexOf('.mov') > -1
				|| state.dialogImageFile.name.indexOf('.avi') > -1"
			w-full
			style="width: 100%;height: 100%;"
			controls
			autoplay
			:src="state.dialogImageFile.url">
			<source :src="state.dialogImageFile.url" type="video/mp4" />
			<source :src="state.dialogImageFile.url" type="video/mov" />
			<source :src="state.dialogImageFile.url" type="video/avi" />
		</video>
	</el-dialog>
</el-form-item>

2、js部分

const state = reactive({
	photoList: [] as any,           // 上传图片
	dialogVisible: false as boolean,
	dialogImageFile: '' as any,
	disabledBtn: false as boolean,
});

// 预览图片和视频
const handlePreview = (file: any) => {
	state.dialogImageFile = file;
	state.dialogVisible = true;
}
// 删除图片视频
const handleRemove = (file: any) => {
	state.photoList.map((item: any, index: number) => {
		if(item.response && item.response.data) {
			if(item.response.data == file.response?.data || item.response.data == file.url) {
				state.photoList.splice(index, 1);
			}
		} else if(item.url) {
			if(item.url == file.response?.data || item.url == file.url) {
				state.photoList.splice(index, 1);
			}
		}
	})
}
// 上传图片
const handleUpload = (res: any) => {
	if(res.code != 0) {
		state.photoList.pop()
		ElMessage.error(res.msg)
	}
}

3、css部分

<style lang="scss" scoped>
    :deep(.hideUpload .el-upload--picture-card)  {
        display: none;
    }
    :deep(.el-upload--picture-card) {
        width: 243px;
        height: 180px;
    }
    :deep(.el-upload-list--picture-card .el-upload-list__item) {
        width: 243px;
        height: 180px;
    }
</style>
### el-upload 上传视频封面不展示的问题及解决方案 `el-upload` 是 Element UI 提供的一个组件,用于实现文件上传功能。当涉及到上传视频显示其封面时,可能会遇到无法正常展示封面的情况。以下是可能的原因分析以及对应的解决方案。 #### 可能原因 1. **未设置 `list-type="picture-card"` 属性** 如果希望在上传完成后能够预览图片视频封面,则需要确保设置了该属性[^1]。 2. **缺少自定义处理逻辑** 默认情况下,`el-upload` 不会自动截取视频的第一帧作为封面。因此,如果要实现这一功能,需通过自定义方法来完成。 3. **返回的数据格式不符合预期** 当服务器端响应数据时,如果没有正确解析或者绑定到前端变量中,也可能导致封面无法显示。 --- #### 解决方案 ##### 方法一:利用 HTML5 的 `<video>` 标签获取视频第一帧作为封面 可以通过 JavaScript 结合 HTML5 的 `<video>` Canvas API 来提取视频的第一帧图像,将其转换为 Base64 字符串以便于展示。 ```javascript function getVideoCover(file, callback) { const video = document.createElement('video'); video.preload = 'metadata'; video.src = URL.createObjectURL(file); video.onloadeddata = function () { const canvas = document.createElement('canvas'); const context = canvas.getContext('2d'); canvas.width = video.videoWidth; canvas.height = video.videoHeight; context.drawImage(video, 0, 0, canvas.width, canvas.height); canvas.toBlob(function (blob) { callback(blob); // 将 Blob 转换为 File 对象或其他形式 }, 'image/jpeg'); URL.revokeObjectURL(video.src); }; } ``` 调用此函数可以生成一张静态的封面图片将其赋值给 `el-image` 或其他容器进行展示[^2]。 ##### 方法二:修改 `el-upload` 组件行为 为了兼容视频类型的文件,在上传前先判断文件类型是否为视频,如果是则执行上述方法生成封面;如果不是,则按照常规流程继续操作。 ```vue <template> <div> <el-upload action="#" :before-upload="handleBeforeUpload" :on-success="handleSuccess" list-type="picture-card"> <i class="el-icon-plus"></i> </el-upload> <!-- 预览区域 --> <el-dialog :visible.sync="dialogVisible"> <img width="100%" :src="coverUrl" alt=""> </el-dialog> </div> </template> <script> export default { data() { return { dialogVisible: false, coverUrl: '' } }, methods: { handleBeforeUpload(file) { if (['video/mp4', 'video/webm'].includes(file.type)) { this.getVideoCover(file).then(cover => { this.coverUrl = URL.createObjectURL(new File([cover], 'cover.jpg')); }); } return true; // 返回 true 表示允许上传 }, async getVideoCover(file) { const video = document.createElement('video'); video.preload = 'metadata'; video.src = URL.createObjectURL(file); await new Promise(resolve => video.onloadedmetadata = resolve); const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); canvas.width = video.videoWidth; canvas.height = video.videoHeight; ctx.drawImage(video, 0, 0, canvas.width, canvas.height); const blob = await new Promise((resolve) => canvas.toBlob(resolve, 'image/jpeg') ); URL.revokeObjectURL(video.src); return blob; }, handleSuccess(response, file) { console.log('上传成功:', response, file); } } }; </script> ``` 以上代码片段展示了如何拦截上传请求 (`before-upload`) 动态生成视频封面的功能[^1]。 --- #### 注意事项 - 确保浏览器支持 HTML5 Video Canvas 功能。 - 若涉及大量视频文件的操作,建议优化性能以减少内存占用。 - 自定义封面生成逻辑可以根据实际需求调整分辨率大小等参数。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山为樽水为沼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值