Vue3实现文件上传、下载及预览全流程详解(含完整接口调用)

server/2025/3/4 17:56:41/

在这里插入图片描述
在这里插入图片描述

文章目录

    • 一、环境准备
      • 1.1 创建Vue3项目
      • 1.2 安装依赖
      • 1.3 配置Element Plus
    • 二、文件上传实现
      • 2.1 基础上传组件
      • 2.2 自定义上传逻辑(Axios实现)
    • 三、文件下载实现
      • 3.1 直接下载(已知文件URL)
      • 3.2 后端接口下载(二进制流)
    • 四、文件预览实现
      • 4.1 图片预览
      • 4.2 PDF预览(使用pdf.js)
      • 4.3 Excel预览(使用xlsx)
    • 五、完整接口示例
      • 5.1 上传接口(Node.js示例)
      • 5.2 下载接口(Node.js示例)
    • 六、注意事项
    • 七、完整项目结构
    • 八、总结

一、环境准备

1.1 创建Vue3项目

npm create vue@latest
# 选择TypeScript、Pinia(可选)、ESLint等配置

1.2 安装依赖

npm install axios element-plus @element-plus/icons-vue

1.3 配置Element Plus

// main.ts
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'const app = createApp(App)
app.use(ElementPlus)

二、文件上传实现

2.1 基础上传组件

<template><el-uploadclass="upload-demo":action="uploadUrl":headers="headers":on-success="handleSuccess":before-upload="beforeUpload"><el-button type="primary">点击上传</el-button><template #tip><div class="el-upload__tip">支持扩展名:.jpg/.png/.pdf,最大5MB</div></template></el-upload>
</template><script setup lang="ts">
import { ref } from 'vue'
import type { UploadProps } from 'element-plus'const uploadUrl = ref('https://api.example.com/upload')
const headers = ref({Authorization: 'Bearer ' + localStorage.getItem('token')
})// 文件预校验
const beforeUpload: UploadProps['beforeUpload'] = (rawFile) => {const isValidType = ['image/jpeg', 'image/png', 'application/pdf'].includes(rawFile.type)const isLt5M = rawFile.size / 1024 / 1024 < 5if (!isValidType) {ElMessage.error('文件格式不支持!')return false}if (!isLt5M) {ElMessage.error('文件大小不能超过5MB!')return false}return true
}// 上传成功回调
const handleSuccess: UploadProps['onSuccess'] = (response) => {ElMessage.success('上传成功')console.log('服务器返回:', response)// 通常返回文件访问地址
}
</script>

2.2 自定义上传逻辑(Axios实现)

const customUpload = async (file: File) => {const formData = new FormData()formData.append('file', file)formData.append('userId', '123')try {const { data } = await axios.post('/api/upload', formData, {headers: {'Content-Type': 'multipart/form-data',Authorization: `Bearer ${localStorage.getItem('token')}`}})return data} catch (error) {ElMessage.error('上传失败')throw error}
}

三、文件下载实现

3.1 直接下载(已知文件URL)

<template><el-button @click="handleDownload">下载文件</el-button>
</template><script setup lang="ts">
const handleDownload = () => {const link = document.createElement('a')link.href = 'https://api.example.com/files/sample.pdf'link.download = 'filename.pdf' // 设置下载文件名document.body.appendChild(link)link.click()document.body.removeChild(link)
}
</script>

3.2 后端接口下载(二进制流)

const downloadFile = async (fileId: string) => {try {const response = await axios.get(`/api/download/${fileId}`, {responseType: 'blob'})// 创建Blob对象const blob = new Blob([response.data])const url = window.URL.createObjectURL(blob)// 提取文件名const contentDisposition = response.headers['content-disposition']const fileName = contentDisposition?.split('filename=')[1]?.replace(/"/g, '')|| 'download-file'// 创建下载链接const link = document.createElement('a')link.href = urllink.download = fileNamedocument.body.appendChild(link)link.click()window.URL.revokeObjectURL(url)document.body.removeChild(link)} catch (error) {ElMessage.error('下载失败')}
}

四、文件预览实现

4.1 图片预览

<template><el-image :src="imageUrl" :preview-src-list="[imageUrl]"fit="cover"/>
</template>

4.2 PDF预览(使用pdf.js)

npm install pdfjs-dist @types/pdfjs-dist
<template><div ref="pdfContainer" class="pdf-viewer"></div>
</template><script setup lang="ts">
import { ref, onMounted } from 'vue'
import * as pdfjsLib from 'pdfjs-dist'const props = defineProps<{pdfUrl: string
}>()const pdfContainer = ref<HTMLElement>()onMounted(async () => {const loadingTask = pdfjsLib.getDocument(props.pdfUrl)const pdf = await loadingTask.promisefor (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {const page = await pdf.getPage(pageNum)const viewport = page.getViewport({ scale: 1.5 })const canvas = document.createElement('canvas')const context = canvas.getContext('2d')!canvas.height = viewport.heightcanvas.width = viewport.widthawait page.render({canvasContext: context,viewport: viewport}).promisepdfContainer.value?.appendChild(canvas)}
})
</script>

4.3 Excel预览(使用xlsx)

npm install xlsx
<template><el-table :data="excelData"><el-table-column v-for="(col, index) in columns":key="index":prop="col":label="col"/></el-table>
</template><script setup lang="ts">
import { read, utils } from 'xlsx'
import { ref } from 'vue'const excelData = ref([])
const columns = ref([])const previewExcel = async (file: File) => {const data = await file.arrayBuffer()const workbook = read(data)const worksheet = workbook.Sheets[workbook.SheetNames[0]]const jsonData = utils.sheet_to_json(worksheet, { header: 1 })columns.value = jsonData[0]excelData.value = jsonData.slice(1).map(row => {return columns.value.reduce((obj, col, index) => {obj[col] = row[index]return obj}, {})})
}
</script>

五、完整接口示例

5.1 上传接口(Node.js示例)

javascript">// Express 路由
app.post('/api/upload', (req, res) => {const multer = require('multer')const upload = multer({ dest: 'uploads/' })upload.single('file')(req, res, (err) => {if (err) return res.status(500).json({ code: 500, message: '上传失败' })// 返回文件信息res.json({code: 200,data: {url: `/files/${req.file.filename}`,originalname: req.file.originalname,size: req.file.size}})})
})

5.2 下载接口(Node.js示例)

javascript">app.get('/api/download/:filename', (req, res) => {const filePath = path.join(__dirname, 'uploads', req.params.filename)res.setHeader('Content-Type', 'application/octet-stream')res.setHeader('Content-Disposition', `attachment; filename=${req.params.filename}`)const fileStream = fs.createReadStream(filePath)fileStream.pipe(res)
})

六、注意事项

  1. 安全验证:所有文件接口需进行身份验证
  2. 文件大小限制:Nginx需配置client_max_body_size
  3. 文件存储
    • 敏感文件不要存储在公开目录
    • 使用OSS云存储更佳
  4. 预览安全
    • 防止XSS攻击(特别处理HTML文件)
    • 使用CSP内容安全策略

七、完整项目结构

/src
├─api/
│  └─file.ts       # 文件相关接口封装
├─components/
│  └─FilePreview.vue # 文件预览组件
├─utils/
│  ├─download.ts   # 下载工具函数
│  └─validation.ts # 文件验证函数

八、总结

本文全面而详尽地实现了多项关键功能,为开发者提供了从前端到后端、从组件开发到接口对接的全方位解决方案。首先,我们基于Element Plus这一流行的Vue3组件库,成功构建了一个高效且用户友好的文件上传组件。该组件不仅支持文件的快速上传,还提供了丰富的用户交互体验,如进度条显示、上传成功/失败提示等,极大地提升了用户的使用感受。

在文件处理方面,我们实现了Axios二进制流文件的下载功能。通过Axios的强大网络请求能力,我们能够轻松地从服务器获取二进制文件流,并将其保存到本地或进行进一步的处理。这一功能为文件的异步下载和动态处理提供了有力支持。

为了满足不同格式文件的预览需求,我们精心设计了一套PDF/Excel/图片多格式的预览方案。该方案能够自动识别文件类型,并调用相应的预览组件进行展示。无论是常见的图片文件,还是复杂的PDF、Excel文档,都能在我们的系统中得到清晰、准确的预览效果。

此外,我们还提供了前后端完整接口示例,展示了如何在Vue3前端与后端服务器之间进行高效的数据交互。通过详细的接口定义和示例代码,开发者可以快速地理解并实现前后端的数据通信,为项目的快速迭代和部署提供了有力保障。

最后,在生产环境注意事项部分,我们总结了在实际部署过程中可能遇到的问题及解决方案,如性能优化、安全性考虑等。这些宝贵的经验分享将帮助开发者更好地将项目从开发环境迁移到生产环境,确保系统的稳定性和可靠性。综上所述,本文不仅提供了丰富的功能实现,还为开发者提供了全面的开发指导和实战经验分享。


http://www.ppmy.cn/server/171894.html

相关文章

Express + MongoDB 实现 VOD 视频点播

一、安装依赖 npm install express mongoose multer ffmpeg-static fluent-ffmpegexpress&#xff1a;用于构建 Web 服务器。mongoose&#xff1a;用于与 MongoDB 进行交互。multer&#xff1a;用于处理文件上传。ffmpeg-static&#xff1a;提供 FFmpeg 的静态二进制文件。flu…

Linux上用C++和GCC开发程序实现两个不同PostgreSQL实例下单个数据库中多个Schema稳定高效的数据迁移到其它PostgreSQL实例

设计一个在Linux上运行的GCC C程序&#xff0c;同时连接三个不同的PostgreSQL实例&#xff0c;其中两个实例中分别有两个数据库中多个Schema的表结构分别与第三实例中两个数据库中多个Schema个结构完全相同&#xff0c;同时复制两个实例中两个数据库中多个Schema里的所有表的数…

NO.21十六届蓝桥杯备战|一维数组|范围for|memset|memcpy(C++)

数组是⼀组相同类型元素的集合 数组中存放的是1个或者多个数据&#xff0c;但是数组元素个数不能为0数组中存放的多个数据&#xff0c;类型是相同的 数组分为⼀维数组和多维数组&#xff0c;多维数组⼀般⽐较多⻅的是⼆维数组 一维数组 ⼀维数组是最常⻅的&#xff0c;通常⽤…

Template Method 设计模式

模板方法模式&#xff08;Template Method Pattern&#xff09; 是一种 行为型设计模式&#xff0c;用于定义 算法的骨架&#xff0c;并允许子类在不改变算法结构的情况下 重新定义 其中的某些步骤。 核心思想&#xff1a; 在 基类 中定义 算法的整体流程&#xff08;骨架&am…

Lua的table(表)

Lua表的基本概念 Lua中的表&#xff08;table&#xff09;是一种多功能数据结构&#xff0c;可以用作数组、字典、集合等。表是Lua中唯一的数据结构机制&#xff0c;其他数据结构如数组、列表、队列等都可以通过表来实现。 表的实现 Lua的表由两部分组成&#xff1a; 数组部分…

塔能科技:工厂智慧照明,从底层科技实现照明系统的智能化控制

在全球节能减碳和智慧生活需求激增的背景下&#xff0c;基于“用软件定义硬件&#xff0c;让物联运维更简捷更节能”的产品理念&#xff0c;塔能科技的智慧照明一体化方案如新星般崛起&#xff0c;引领照明行业新方向。现在&#xff0c;我们来深入探究其背后的创新技术。该方案…

应对现代生活的健康养生指南

在科技飞速发展的现代社会&#xff0c;人们的生活方式发生了巨大改变&#xff0c;随之而来的是一系列健康问题。快节奏的生活、高强度的工作以及电子产品的过度使用&#xff0c;让我们的身体承受着前所未有的压力。因此&#xff0c;掌握正确的健康养生方法迫在眉睫。 针对久坐不…

服务器间免密登录

1. 生成SSH密钥对 在本地客户端生成SSH密钥对。生成密钥对命令为&#xff1a; ssh-keygen -t rsa 按回车键确认默认设置&#xff0c;生成的密钥对将保存在 ~/.ssh/id_rsa&#xff08;私钥&#xff09;和 ~/.ssh/id_rsa.pub&#xff08;公钥&#xff09;。 2. 上传密钥对至需…