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

相关推荐
猿饵块26 分钟前
cmake--get_filename_component
java·前端·c++
大表哥637 分钟前
在react中 使用redux
前端·react.js·前端框架
十月ooOO42 分钟前
【解决】chrome 谷歌浏览器,鼠标点击任何区域都是 Input 输入框的状态,能看到输入的光标
前端·chrome·计算机外设
qq_3391911442 分钟前
spring boot admin集成,springboot2.x集成监控
java·前端·spring boot
pan_junbiao1 小时前
Vue使用代理方式解决跨域问题
前端·javascript·vue.js
明天…ling1 小时前
Web前端开发
前端·css·网络·前端框架·html·web
ROCKY_8171 小时前
web前端-HTML常用标签-综合案例
前端·html
海石1 小时前
从0到1搭建一个属于自己的工作流站点——羽翼渐丰(bpmn-js、Next.js)
前端·javascript·源码
Q186000000001 小时前
在HTML中添加图片
前端·html
傻虎贼头贼脑1 小时前
day21JS-npm中的部分插件使用方法
前端·npm·node.js