基于 Element Plus 的文件上传和预览组件实现

使用 Vue 3 和 el-upload 实现文件上传与自定义粘贴板图像上传功能

在这篇文章中,我们将详细介绍如何在 Vue 3 项目中使用 Element Plus 的 el-upload 组件实现文件上传。此实现不仅支持多种文件类型(如图片、视频、PDF 和 Excel 文件),还提供了从剪贴板直接粘贴图片上传的功能。通过自定义预览模板和手动管理文件列表,我们实现了灵活的上传和展示功能。

1. 基本的 el-upload 组件设置

首先,el-upload 组件是一个高度灵活的文件上传组件。我们可以通过多个 props 自定义其行为和样式。

ini 复制代码
<el-upload
    ref="uploadRef"
    :action="action"
    :headers="headers"
    :multiple="multiple"
    :data="data"
    :name="name"
    :with-credentials="withCredentials"
    :show-file-list="showFileList"
    :drag="drag"
    :accept="accept"
    :list-type="listType"
    :auto-upload="autoUpload"
    :file-list="fileList"
    :http-request="httpRequest"
    :disabled="disabled"
    :limit="limit"
    @success="handleUploadSuccess"
    @error="handleUploadError"
    @remove="handleFileRemove"
    @preview="handlePictureCardPreview"
    @change="handleFileChange"
    :before-upload="beforeUpload"
/>

2. 自定义文件预览模板

我们可以通过插槽来自定义上传文件的预览模板。例如,根据文件类型显示不同的预览样式,如图片、视频、Excel 文件或 PDF 文件。

xml 复制代码
<template #file="{ file }">
    <div>
        <img v-if="isImage(file.url)" class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
        <video v-else-if="isVideo(file.url)" controls style="width: 100%; height: 100%">
            <source :src="file.url" type="video/mp4" />
        </video>
        <el-button v-else-if="isExcelFile(file.url)" size="default" type="warning">
            <el-icon><ele-Download /></el-icon>{{ file.originalName }}
        </el-button>
        <iframe v-else-if="isPdf(file.url)" :src="file.url" width="100%" height="100%"></iframe>
        <span class="el-upload-list__item-actions">
            <span @click="handlePictureCardPreview(file)">
                <el-icon><ele-ZoomIn /></el-icon>
            </span>
            <span @click="handleDownload(file)">
                <el-icon><ele-Download /></el-icon>
            </span>
        </span>
    </div>
</template>

3. 粘贴板图片自动上传功能

在很多应用场景下,用户直接复制截图或图片并粘贴上传是一个非常实用的功能。我们通过监听 paste 事件来实现该功能。

typescript 复制代码
<div class="paste-box d-flex a-center j-center" v-if="!disabled" @paste="onPaste">
    <span class="paste-tip-text">Ctrl+V<br />可粘贴截图</span>
</div>

在 JavaScript 逻辑中,通过 onPaste 函数处理粘贴事件。我们提取粘贴内容中的图像文件,并调用 el-upload 组件的 submit 方法来自动上传。

ini 复制代码
const onPaste = (event: ClipboardEvent) => {
    if (props.disabled) return;
    const clipboardData = event.clipboardData;
    if (clipboardData) {
        const items = clipboardData.items;
        for (let i = 0; i < items.length; i++) {
            const item = items[i];
            if (item.kind === 'file' && item.type.startsWith('image/')) {
                const file = item.getAsFile();
                if (file) {
                    uploadRef.value.handleStart(file);
                    uploadRef.value.submit();
                }
            }
        }
    }
};

4. 文件上传成功后的处理

在文件上传成功后,我们需要更新文件列表,确保列表中不包含临时的 blob: URL。这里我们自定义了 handleUploadSuccess 函数来处理文件上传的成功响应,并使用 replaceBlobUrls 方法来替换文件列表中的临时 URL。

typescript 复制代码
const handleUploadSuccess = (response: any, file: UploadUserFile, files: UploadFiles) => {
    emit('upload-success', response, file, replaceBlobUrls(files));
    fileList.value = replaceBlobUrls(files);
    emit('update:fileList', fileList.value);
};

const replaceBlobUrls = (array: any[]) => {
    const updatedArray = array.map((item) => {
        if (item.url && item.url.includes('blob:')) {
            return item.response.data;
        }
        return item;
    });
    return Array.from(new Set(updatedArray.map(item => JSON.stringify(item)))).map(item => JSON.parse(item));
};

5. 文件删除、预览和下载功能

我们还实现了文件删除、预览和下载的功能。通过 handleFileRemove 函数,我们可以从文件列表中删除特定文件。对于文件预览,我们实现了一个对话框展示,并根据文件类型(图片、视频等)进行不同的展示。

ini 复制代码
const handleFileRemove = (file: UploadUserFile) => {
    fileList.value = fileList.value.filter((f) => f !== file);
    emit('file-remove', file);
    emit('update:fileList', fileList.value);
};

const handlePictureCardPreview = (file: UploadUserFile) => {
    index.value = arrayimg(fileList.value, file.url);
    dialogImageUrl.value = file.url;
    dialogVisible.value = true;
};

const handleDownload = (file: UploadUserFile) => {
    const link = document.createElement('a');
    link.href = file.url;
    link.download = file.originalName || 'download';
    link.click();
};

总结

通过使用 Vue 3 和 Element Plus 的 el-upload 组件,我们可以非常灵活地处理多种文件类型的上传、预览、删除和下载功能。剪贴板图片自动上传的功能为用户带来了更便捷的体验。在项目中,我们可以根据需求进一步扩展这些功能,如添加上传进度、错误处理和更多文件类型支持。

相关推荐
m0_748247552 小时前
Web 应用项目开发全流程解析与实战经验分享
开发语言·前端·php
m0_748255023 小时前
前端常用算法集合
前端·算法
真的很上进3 小时前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
web130933203983 小时前
vue elementUI form组件动态添加el-form-item并且动态添加rules必填项校验方法
前端·vue.js·elementui
NiNg_1_2343 小时前
Echarts连接数据库,实时绘制图表详解
前端·数据库·echarts
如若1234 小时前
对文件内的文件名生成目录,方便查阅
java·前端·python
滚雪球~5 小时前
npm error code ETIMEDOUT
前端·npm·node.js
沙漏无语5 小时前
npm : 无法加载文件 D:\Nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本
前端·npm·node.js
supermapsupport5 小时前
iClient3D for Cesium在Vue中快速实现场景卷帘
前端·vue.js·3d·cesium·supermap
brrdg_sefg5 小时前
WEB 漏洞 - 文件包含漏洞深度解析
前端·网络·安全