您的位置:首页 > 文旅 > 美景 > Vue封装文件上传组件(支持图片、PDF、Excel、word预览下载)

Vue封装文件上传组件(支持图片、PDF、Excel、word预览下载)

2024/10/6 14:34:55 来源:https://blog.csdn.net/qq_36854073/article/details/140516228  浏览:    关键词:Vue封装文件上传组件(支持图片、PDF、Excel、word预览下载)

一、准备工作

安装预览依赖包:exceljs、mammoth、vue-pdf

二、封装组件

文件上传组件

fileUploadPro.vue。默认预览、下载是true,可通过isPreView、isDownLoad控制

<template><div style="display: flex"><el-uploadmultipleaction=""ref="uploadF":show-file-list="false":file-list="fileList":http-request="fileUpLoad"><el-button v-if="!readOnly" size="mini" type="primary">点击上传</el-button></el-upload><div style="flex-grow: 1;flex-wrap: wrap"><el-tag@close="removeFile(index)"v-for="(tag, index) in fileList":key="tag.fileId":closable="true"type="info"><div style="float: left">{{tag.name}}</div><div v-if="isPreView" class="iconStyle" @click="preView(tag)"><i  class="el-icon-view"></i></div><div v-if="isDownLoad" class="iconStyle" @click="downLoad(tag)"><i  class="el-icon-download"></i></div></el-tag></div></div>
</template>
<script>export default {name: "fileUploadPro",props: {fileList: {type: Array,default: []},isPreView: {type: Boolean,default: true},isDownLoad: {type: Boolean,default: true},readOnly:{type: Boolean,default: false}},data() {return {}},methods:{fileUpLoad(e) {let file = e.filelet formData = new FormData();formData.append("file", file); // 'file' 可变 相当于 input 表单的name 属性formData.append("name", file.name);formData.append("type", file.type);formData.append("size", file.size);formData.append("lastModifiedDate", file.lastModifiedDate);this.$http({method: 'post',url: "/base/ctBaseFile/saveFile50",data: formData}).then((response) => {if (response.data.code === 200) {this.$message.success('上传成功')this.fileList.push({fileId: response.data.data.ctBaseFile.id,name: file.name})}})},removeFile(index) {this.fileList.splice(index, 1)},preView(file) {let fileUrl = '';let fileType = '';if (file) {fileUrl = this.$fileUrl + '/common/getFileRes/' + file.fileIdconst addTypeArray = file.name.split(".");const addType = addTypeArray[addTypeArray.length - 1];if (addType === "pdf") {fileType = 'pdf'}else if(addType === 'xls' || addType === 'xlsx'){fileType = 'excel'}else if (addType === "doc" || addType === "docx") {fileType = 'word'} else if (["png", "jpg", "jpeg"].includes(addType)) {fileType = 'image'} else {fileType = addType}}this.$emit("preView",fileType,fileUrl);//that.showModal = true},downLoad(file){let a = document.createElement("a");//创建a标签a.setAttribute("href", this.$fileUrl + '/common/getFileRes/' + file.fileId);//设置文件下载地址a.setAttribute('target', '_blank');//在当前页面创建下载document.body.appendChild(a);//添加到bodya.click();//触发事件document.body.removeChild(a);//移除标签},}}
</script>
<style scope>.iconStyle{float: left;width: 16px;height: 16px;line-height: 16px;text-align: center;position: relative;top:7px;margin-left: 6px;border-radius: 50%;cursor: pointer;}.iconStyle:hover{background-color: #909399;color: #fff;}
</style>

预览组件

preViewDialog.vue

<template><div><!-- Modal --><el-dialog:title="'预览' + fileType":visible.sync="showModal"width="70%"top="5vh":before-close="handleClose":close-on-click-modal="false"><!-- Conditional rendering based on fileType --><div v-if="fileType === 'image'" style="text-align:center"><img v-loading="loading" style="height: 400px" :src="fileUrl" alt="预览图片"></div><div v-else-if="fileType === 'excel'"><el-table v-loading="loading" size="mini" :data="excelData" height="400" width="100%" :show-header="false"><el-table-column width="150" v-for="(cell, key) in excelData[0]" :key="key" :prop="key" :label="key"></el-table-column></el-table></div><div v-else-if="fileType === 'pdf'"><!-- Render PDF preview here --><VuePdf v-loading="loading" :src="pdfUrl"></VuePdf></div><div v-else-if="fileType === 'word'"><!-- Render Word preview here --><div v-loading="loading" v-html="wordContent"></div></div><div v-else><p>不支持的文件类型或未提供URL。</p></div><!-- Close Button --><span slot="footer" class="dialog-footer"><el-button type="primary" @click="downLoad(fileUrl)">下 载</el-button><el-button type="info" @click="closeModal">关 闭</el-button></span></el-dialog></div>
</template><script>import ExcelJS from 'exceljs';import mammoth from 'mammoth';import VuePdf from 'vue-pdf';export default {props: {fileType: {type: String,required: true,},fileUrl: {type: String,required: true}},components: {VuePdf,},data() {return {pdfUrl:'',loading: true,excelContent: '',wordContent: '',showModal: false,excelData: [],};},mounted() {this.showModal = truethis.loadFile();},methods: {async loadFile() {switch (this.fileType) {case 'excel':await this.loadExcel();break;case 'word':await this.loadWord();break;case 'pdf':// 加载 PDF 的逻辑await this.loadPdf();break;default:this.loading = false;break;}},closeModal() {this.loading = true;this.$emit('close-modal');},async loadExcel() {try {const response = await fetch(this.fileUrl);if (!response.ok) {throw new Error(`HTTP error! Status: ${response.status}`);}const arrayBuffer = await response.arrayBuffer();const workbook = new ExcelJS.Workbook();await workbook.xlsx.load(arrayBuffer);const worksheet = workbook.worksheets[0]; // Assuming you want the first worksheetif (worksheet) {let data = [];worksheet.eachRow((row, rowIndex) => {let rowData = {};row.eachCell((cell, colIndex) => {rowData[`col${colIndex}`] = cell.value;});data.push(rowData);});this.excelData = data;} else {this.excelData = [];}} catch (error) {console.error('Error loading Excel:', error);this.excelData = [];} finally {this.loading = false;}},async loadWord() {try {const response = await fetch(this.fileUrl);const arrayBuffer = await response.arrayBuffer();const result = await mammoth.extractRawText({ arrayBuffer });this.wordContent = result.value;} catch (error) {this.wordContent = '加载Word文件失败。';} finally {this.loading = false;}},async loadPdf() {try {this.pdfUrl = VuePdf.createLoadingTask({url:this.fileUrl,cMapUrl: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.6.347/cmaps/',cMapPacked: true})const response = await fetch(this.pdfUrl);if (!response.ok) {throw new Error(`HTTP error! Status: ${response.status}`);}} catch (error) {console.error('Error fetching data:', error);}finally {this.loading = false}},handleClose() {this.closeModal()},downLoad(file){let a = document.createElement("a");//创建a标签a.setAttribute("href", file);//设置文件下载地址a.setAttribute('target', '_blank');//在当前页面创建下载document.body.appendChild(a);//添加到bodya.click();//触发事件document.body.removeChild(a);//移除标签},},};
</script><style scoped>
</style>

三、组件调用

<template><div><fileUploadPro:file-list.sync="fileList":isPreView="true":isDownLoad="false"@preView="preView"/><previewDialogv-if="showModal":file-type="fileType":file-url="fileUrl"@close-modal="showModal = false"/></div>
</template>
<script>import previewDialog from '../components/previewDialog';import fileUploadPro from "../components/fileUploadPro";export default {name: "parentXXX",components:{previewDialog,fileUploadPro},data() {return{fileList:[],fileType: '',fileUrl:'',showModal: false,}},methods:{preView(type,url){this.fileUrl = url;this.fileType = type;this.showModal = true},}}
</script>

四、效果

 

 

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com