一、情况准备
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-upload
- class="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 < 5
-
- if (!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 = url
- link.download = fileName
- document.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.promise
-
- for (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.height
- canvas.width = viewport.width
-
- await page.render({
- canvasContext: context,
- viewport: viewport
- }).promise
-
- pdfContainer.value?.appendChild(canvas)
- }
- })
- </script>
复制代码 4.3 Excel预览(利用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示例)
- // 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示例)
- 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)
- })
复制代码 六、注意事项
- 安全验证:所有文件接口需举行身份验证
- 文件大小限制:Nginx需设置client_max_body_size
- 文件存储:
- 预览安全:
- 防止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前端与后端服务器之间举行高效的数据交互。通过具体的接口定义和示例代码,开辟者可以快速地理解并实现前后端的数据通讯,为项目标快速迭代和部署提供了有力保障。
最后,在生产情况注意事项部门,我们总结了在实际部署过程中大概碰到的标题及解决方案,如性能优化、安全性考虑等。这些名贵的经验分享将帮助开辟者更好地将项目从开辟情况迁移到生产情况,确保系统的稳定性和可靠性。综上所述,本文不仅提供了丰富的功能实现,还为开辟者提供了全面的开辟指导和实战经验分享。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |