vue实现文件预览和文件上传、下载、预览——多图、模型、dwg图纸、文档(word、excel、ppt、pdf)

news/2024/10/17 5:44:04/

整体思路(模型特殊不考虑,别人封装不具备参考性)

  1. 图片上传采用单独的组件,其他三种类型采用一个上传组件(仅仅文件格式不同)
  2. 文件上传采用前端直接上传阿里云的方式
  3. 图片预览使用elementUI自带的image预览
  4. dwg预览采用 kkfileview 方式,需要后台部署,前端使用 npm install js-base64 ,应该支持所有文件的预览,我们这里仅用作CAD文件的预览
  5. 文档类型的直接在浏览器打开预览,如果不支持需要拼接前缀 "https://view.officeapps.live.com/op/view.aspx?src="
  6. 图片下载为压缩包
  7. 文档类的相同方法下载

上传

在这里插入图片描述

        <el-formstyle="width: 650px":model="form":rules="rules"ref="form"label-width="180px"word">class="demo-form":disabled="type == 3"><el-form-item label="样板格式" prop="modelType"><el-radio-group v-model="form.modelType"><el-radio label="1">图片样板</el-radio><el-radio label="2">三维样板</el-radio><el-radio label="3">图纸样板</el-radio><el-radio label="4">文档样板</el-radio></el-radio-group></el-form-item><!-- 1 图片样板 2 三维样板 3 图纸样板 4 文档样板 --><el-form-itemv-word">if="form.modelType == 1"label="样板文件上传"prop="url"><ImageUploadv-model="form.url"tip="请上传图片:":limit="10":showIcon="type == 3 ? true : false"></ImageUpload></el-form-item><el-form-itemv-word">if="form.modelType != 1"label="样板文件上传"prop="url"><ModelUploadv-word">if="type != 3"v-model="form.url":limit="1":fileSize="form.modelType == 3 ? 50 : form.modelType == 4 ? 10 : 5120":isShowUploadModel="true"ref="videoUploadRef"@input="uploadTemplate":fileType="form.modelType == 3? ['.dwg']: form.modelType == 4? ['.doc', '.docx', '.xls', '.xlsx', '.ppt', '.pptx', '.pdf']: ['.rvt', '.ifc', '.obj', '.stl', '.fbx', '.3DS']"></ModelUpload><div v-word">else word">class="blue point" @click="preview(form)">{{ form.url?.split("/")[form.url?.split("/").length - 1] }}</div></el-form-item>

ModelUpload.vue

<template><div word">class="component-upload-image"><el-uploadaction="":http-request="beforeUpload"word">class="avatar-uploader":limit="limit":on-remove="handleDelete":on-error="handleUploadError":on-exceed="handleExceed"name="file":show-file-list="true":file-list="fileList"ref="uploadRef":on-preview="handlePreview":data="otherQuery"><el-buttonsize="small"type="primary"v-word">if="!modelFlag":disabled="disabled">点击上传</el-button><!-- 上传提示 --><div word">class="el-upload__tip" slot="tip" v-word">if="showTip"><template v-word">if="fileSize">大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b></template><template v-word">if="fileType">文件类型支持<b style="color: #f56c6c">{{ fileType.join(" / ") }}</b> 格式</template></div><el-progressv-word">if="modelFlag == true"type="circle":percentage="modelUploadPercent"style="margin-top: 7px"></el-progress></el-upload></div>
</template><script>
word">export word">default {props: {value: [String, Object, Array],// 图片数量限制limit: {type: Number,word">default: 1,},// 大小限制(MB)fileSize: {type: Number,word">default: 5120,},fileType: {type: Array,default: () => [".rvt", ".ifc", ".dwg", ".obj", ".stl", ".fbx", ".3DS"],},// 是否显示提示isShowTip: {type: Boolean,word">default: true,},// 是否显示进度条isShowUploadModel: {type: Boolean,word">default: false,},// 是否显示重新上传按钮isShowBtn: {type: Boolean,word">default: true,},// 是否禁用上传按钮disabled: {type: Boolean,word">default: false,},},data() {word">return {number: 0,hideUpload: false,fileList: [],otherQuery: {}, //上传文件传递额外参数uploadList: [],modelFlag: false,modelUploadPercent: 0,isCancel: false,};},watch: {value: {handler(val) {word">if (val) {console.log(val, "val");word">if (word">typeof val == "string") {// 首先将值转为数组word">const list = Array.isArray(val) ? val : word">this.value.split(",");// 然后将数组转为对象数组word">this.fileList = list.map((item) => {word">if (word">typeof item === "string") {item = {name: item.substring(item.lastIndexOf("/") + 14),url: item,};}word">return item;});} word">else {val.forEach((el) => {el.name = el.fileName;});word">this.fileList = val;}} word">else {word">this.fileList = [];word">return [];}},deep: true,immediate: true,},},computed: {// 是否显示提示showTip() {word">return word">this.isShowTip && (word">this.fileType || word">this.fileSize);},},methods: {//自定义上传方法..Upload(file, data) {console.log(file);word">let OSS = require("ali-oss");word">let client = word">new OSS({region: data.region,accessKeyId: data.accessKeyId,accessKeySecret: data.accessKeySecret,// accessKeyId: "",// accessKeySecret: "",bucket: "cscec83-openfile",});// let cdnUrl = data.cdnUrl;word">let cdnUrl = "https://cscec83-openfile.oss-cn-shanghai.aliyuncs.com/";word">this.number++;word">this.isCancel = false;word">const progress = (p, _checkpoint) => {console.log(p);// console.log(_checkpoint);word">this.modelFlag = true;word">this.modelUploadPercent = Number((Number(p) * 100).toFixed(1));console.log(word">this.isCancel);word">if (word">this.isCancel) {client.cancel();}};word">let fileName = "model/" + word">new Date().getTime() + file.file.name;client.multipartUpload(fileName, file.file, {progress,// 设置并发上传的分片数量。// parallel: 4,// 设置分片大小。默认值为1 MB,最小值为100 KB。partSize: 5 * 1024 * 1024,}).then((res) => {// console.log(res, "res");word">this.modelFlag = false;word">if (res.name) {word">let obj = {fileName: res.name,name: res.name,size: word">this.otherQuery.size,url: cdnUrl + res.name,};console.log(cdnUrl + res.name);word">this.uploadList.push(obj);word">if (word">this.uploadList.length === word">this.number) {word">this.fileList = word">this.fileList.concat(word">this.uploadList);word">this.uploadList = [];word">this.number = 0;// let list = this.fileList.map((item) => {//   return {//     ...item,//     modelUrl: item.url,//   };// });word">this.$emit("input", word">this.fileList);}} word">else {word">this.$modal.msgError("上传失败,请重试");word">this.cancel();}}).catch((err) => {console.log(err);word">if (err.name == "cancel") {word">this.$message("上传取消");} word">else {word">this.$modal.msgError(err);}word">this.cancel();});},handleDelete(file) {word">const findex = word">this.fileList.map((f) => f.fileName).indexOf(file.fileName);word">if (findex > -1) {word">this.fileList.splice(findex, 1);word">this.$emit("input", word">this.fileList);}word">this.cancel();},// 上传前loading加载beforeUpload(file) {console.log(word">this.fileType, file.file.name);word">this.otherQuery = {};word">this.isCancel = false;word">var fileSize = file.file.size / 1024 / 1024 < word">this.fileSize; //控制大小  修改50的值即可word">let fileType = file.file.name.substring(file.file.name.lastIndexOf("."));word">let isContinue = true;word">if (word">this.fileType.indexOf(fileType) == -1 //控制格式) {word">this.$modal.msgError(`文件格式不正确, 请上传${word">this.fileType.join("/")}格式文件!`);word">this.fileList = [];isContinue = false;}word">if (!fileSize) {word">this.$modal.msgError(`上传视频大小不能超过 ${word">this.fileSize} MB!`);word">this.fileList = [];isContinue = false;}word">this.otherQuery.fileName = file.file.name;word">this.otherQuery.size = (file.file.size / 1024 / 1024).toFixed(2);word">if (!isContinue) word">return;word">this.$axios.get("/file/ossFile/getOssParameter").then((res) => {word">if (res.code == 200) {word">this.Upload(file, res.data);}});},// 预览handlePreview(file) {window.open(file.url, "_blank");},// 文件个数超出handleExceed() {word">this.$message.error(`上传文件数量不能超过 ${word">this.limit} 个!`);},// 上传失败handleUploadError() {word">this.$modal.msgError("上传失败,请重试");// this.loading.close();},cancel(type) {word">this.isCancel = true;word">this.modelFlag = false;},},
};
</script>
<style scoped lang="css">
::v-deep.hideUpload .el-upload--picture-card {display: none;
}::v-deep .el-upload--picture-card {width: 104px;height: 104px;line-height: 104px;
}::v-deep .el-upload-list--picture-card .el-upload-list__item {width: 104px;height: 104px;
}.avatar-uploader-icon {border: 1px dashed #d9d9d9 !important;
}.avatar-uploader .el-upload {border: 1px dashed #d9d9d9 !important;border-radius: 6px !important;position: relative !important;overflow: hidden !important;
}.avatar-uploader .el-upload:hover {border: 1px dashed #d9d9d9 !important;border-color: #409eff;
}.avatar-uploader-icon {font-size: 28px;color: #8c939d;width: 300px;height: 178px;line-height: 178px;text-align: center;
}.avatar {width: 300px;height: 178px;display: block;
}
</style>

ImageUpload.vue

<template><div word">class="component-upload-image"><el-uploadmultiple:action="uploadImgUrl"list-type="picture-card":on-success="handleUploadSuccess":before-upload="handleBeforeUpload":limit="limit":on-error="handleUploadError":on-exceed="handleExceed"name="file":disabled="showIcon":on-remove="handleRemove":show-file-list="true":headers="headers":file-list="fileList":on-preview="handlePictureCardPreview":word">class="{hideUpload: word">this.fileList.length >= word">this.limit || word">this.showIcon,}"><i word">class="el-icon-plus"></i></el-upload><!-- 上传提示 --><div word">class="el-upload__tip" slot="tip" v-word">if="showTip">{{ tip }}<template v-word">if="fileSize">大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b></template><template v-word">if="fileType">格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b></template></div><el-dialog:visible.sync="dialogVisible"title="预览"width="800"append-to-body><img:src="dialogImageUrl"style="display: block; max-width: 100%; margin: 0 auto"/></el-dialog></div>
</template><script>
word">export word">default {props: {value: [String, Object, Array],// 图片数量限制limit: {type: Number,word">default: 5,},// 大小限制(MB)fileSize: {type: Number,word">default: 10,},// 文件类型, 例如['png', 'jpg', 'jpeg']fileType: {type: Array,default: () => ["png", "jpg", "jpeg"],},tip: {type: String,},// 是否显示提示isShowTip: {type: Boolean,word">default: true,},// 是否禁用添加图片按钮showIcon: {type: Boolean,word">default: false,},},data() {word">return {number: 0,uploadList: [],dialogImageUrl: "",dialogVisible: false,hideUpload: false,uploadImgUrl: "/prod-api" + "/file/upload", // 上传的图片服务器地址headers: {Authorization: word">this.$store.state.token,},fileList: [],};},watch: {value: {handler(val) {word">if (val) {// 首先将值转为数组word">const list = Array.isArray(val) ? val : word">this.value.split(",");// 然后将数组转为对象数组word">this.fileList = list.map((item) => {word">if (word">typeof item === "string") {item = { name: item, url: item };}word">return item;});} word">else {word">this.fileList = [];word">return [];}},deep: true,immediate: true,},},computed: {// 是否显示提示showTip() {word">return word">this.isShowTip && (word">this.fileType || word">this.fileSize);},},methods: {// 删除图片handleRemove(file, fileList) {word">const findex = word">this.fileList.map((f) => f.name).indexOf(file.name);word">if (findex > -1) {word">this.fileList.splice(findex, 1);word">this.$emit("input", word">this.listToString(word">this.fileList));}},// 上传成功回调handleUploadSuccess(res) {word">this.uploadList.push({ name: res.data.url, url: res.data.url });word">if (word">this.uploadList.length === word">this.number) {word">this.fileList = word">this.fileList.concat(word">this.uploadList);word">this.uploadList = [];word">this.number = 0;word">this.$emit("input", word">this.listToString(word">this.fileList));word">this.$modal.closeLoading();}},// 上传前loading加载handleBeforeUpload(file) {word">let isImg = false;word">if (word">this.fileType.length) {word">let fileExtension = "";word">if (file.name.lastIndexOf(".") > -1) {fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);}isImg = word">this.fileType.some((type) => {word">if (file.type.indexOf(type) > -1) word">return true;word">if (fileExtension && fileExtension.indexOf(type) > -1) word">return true;word">return false;});} word">else {isImg = file.type.indexOf("image") > -1;}word">if (!isImg) {word">this.$modal.msgError(`文件格式不正确, 请上传${word">this.fileType.join("/")}图片格式文件!`);word">return false;}word">if (word">this.fileSize) {word">const isLt = file.size / 1024 / 1024 < word">this.fileSize;word">if (!isLt) {word">this.$modal.msgError(`上传头像图片大小不能超过 ${word">this.fileSize} MB!`);word">return false;}}word">this.$modal.loading("正在上传图片,请稍候...");word">this.number++;},// 文件个数超出handleExceed() {word">this.$modal.msgError(`上传文件数量不能超过 ${word">this.limit} 个!`);},// 上传失败handleUploadError() {word">this.$modal.msgError("上传图片失败,请重试");word">this.$modal.closeLoading();},// 预览handlePictureCardPreview(file) {word">this.dialogImageUrl = file.url;word">this.dialogVisible = true;},// 对象转成指定字符串分隔listToString(list, separator) {word">let strs = "";separator = separator || ",";word">for (word">let i word">in list) {strs += list[i].url + separator;}word">return strs != "" ? strs.substr(0, strs.length - 1) : "";},},
};
</script>
<style scoped >
::v-deep.hideUpload .el-upload--picture-card {display: none;
}::v-deep .el-upload--picture-card {width: 86px;height: 86px;line-height: 86px;
}::v-deep .el-upload-list--picture-card .el-upload-list__item {width: 86px;height: 86px;
}::v-deep .el-list-enter-active,
::v-deep .el-list-leave-active {transition: all 0s;
}::v-deep .el-list-enter,
.el-list-leave-active {opacity: 0;transform: translateY(0);
}
</style>

预览和下载

在这里插入图片描述

<template><div id="index"><el-card shadow="always" style="margin-top: 20px"><div word">class="model pd-16"><div word">class="flex mb-20"><div word">class="title-left bold size-22">工程样板</div><divword">class="flex_r point border-blue blue plr-10 ptb-4 bg-white radius-4 size-14"@click="toTemplate">查看更多 <i word">class="el-icon-right"></i></div></div><div word">class="flex_l"><divword">class="center mr-20 plr-20 ptb-10"@click="changeTab(1)":style="tab == 1? 'background: linear-gradient(210.65deg, #5FA4FE 0%, #367EF8 100%);border-radius: 25px;color:#fff': ''"><img:src="`${tab == 1? require('../../assets/img/zhi-tab-1-1.png'): require('../../assets/img/zhi-tab-1.png')}`"alt=""style="width: 27px"/><div word">class="ml-16 size-18">图片区</div></div><divword">class="center mr-20 plr-20 ptb-10"@click="changeTab(2)":style="tab == 2? 'background: linear-gradient(210.65deg, #5FA4FE 0%, #367EF8 100%);border-radius: 25px;color:#fff': ''"><img:src="`${tab == 2? require('../../assets/img/zhi-tab-4-1.png'): require('../../assets/img/zhi-tab-4.png')}`"alt=""style="width: 27px"/><div word">class="ml-16 size-18">三维模型区</div></div><divword">class="center mr-20 plr-20 ptb-10"@click="changeTab(3)":style="tab == 3? 'background: linear-gradient(210.65deg, #5FA4FE 0%, #367EF8 100%);border-radius: 25px;color:#fff': ''"><img:src="`${tab == 3? require('../../assets/img/zhi-tab-3-1.png'): require('../../assets/img/zhi-tab-3.png')}`"alt=""style="width: 27px"/><div word">class="ml-16 size-18">图纸区</div></div><divword">class="center mr-20 plr-20 ptb-10"@click="changeTab(4)":style="tab == 4? 'background: linear-gradient(210.65deg, #5FA4FE 0%, #367EF8 100%);border-radius: 25px;color:#fff': ''"><img:src="`${tab == 4? require('../../assets/img/zhi-tab-2-1.png'): require('../../assets/img/zhi-tab-2.png')}`"alt=""style="width: 27px"/><div word">class="ml-16 size-18">文档区</div></div></div><el-row :gutter="20" word">class="mt-30"><div v-word">if="templateList.length == 0" word">class="text-center"><img src="../../assets/img/null.png" alt="" style="width: 4rem" /><div>暂无数据</div></div><el-col :span="6" v-word">for="(item, i) in templateList" :key="i + 'c'"><el-card shadow="hover" word">class="point course mb-12"><el-imagev-word">if="tab == 1"style="width: 100%; height: 170px; border-radius: 5px"mode="aspectFill":src="item.pictureUrl":preview-src-list="[item.url.split(',')]"></el-image><img@click="preview(item)"v-word">if="tab == 2 || tab == 3 || tab == 4":src="tab == 4? require(`../../assets/img/doc-${item.docType || 'word'}.png`): item.pictureUrl"style="width: 100%; height: 170px; border-radius: 5px"mode="aspectFill"/><div word">class="flex mtb-10 mlr-12"><div word">class="line-1 mr-10">{{ item.modelName }}</div><imgstyle="width: 22px"src="../../assets/img/download.png"alt=""@click.stop="download(item)"/></div></el-card></el-col></el-row></div></el-card><modelPop ref="modelPopRef"></modelPop></div></div>
</template><script>
// npm install js-base64
word">import { Base64 } word">from "js-base64";
word">export word">default {// layout: "default-all",data() {word">return {tab: 1,templateList: [],};},mounted() { word">this.getTemplateList();},methods: {changeTab(tab) {word">this.tab = tab;word">this.getTemplateList();},// 下载download(item) {// 1 图片样板 2 三维样板 3 图纸样板 4 文档样板word">if (word">this.tab == 1) {word">this.$downloadZip.zip("/qualityTrain/sample/downloadAndZip?sampleId=" + item.sampleId,item.modelName + "样板文件.zip");} word">else word">if (word">this.tab == 2 || word">this.tab == 3) {window.open(item.url);} word">else word">if (word">this.tab == 4) {fetch(item.url).then((res) => res.blob()).then((blob) => {word">const a = document.createElement("a");word">const objectUrl = window.URL.createObjectURL(blob);a.download =item.modelName +(item.docType == "ppt"? ".ppt": item.docType == "excel"? ".xls": item.docType == "word"? ".doc": ".pdf");a.href = objectUrl;a.click();});}},getTemplateList() {word">this.$axios.get("/qualityTrain/sample/homePage", {params: {modelType: word">this.tab,},}).then((res) => {word">this.templateList = res.data;});},// 预览preview(item) {// 1 图片样板 2 三维样板 3 图纸样板 4 文档样板word">if (word">this.tab == 2) {word">this.$refs.modelPopRef.init(item.sampleId, item.modelName, false, true);} word">else word">if (word">this.tab == 3) {word">let base = location.protocol + "//" + location.hostname + ":8012";word">let url =(base.includes("192.168.2.89") ? "http://192.168.0.19:8012" : base) +"/onlinePreview?url=" +encodeURIComponent(Base64.encode(item.url));window.open(url, "_blank");} word">else {console.log(item.docType);window.open((item.docType != "pdf"? "https://view.officeapps.live.com/op/view.aspx?src=": "") + item.url);}},},
};
</script> 

downloadZip.js

word">import axios word">from 'axios'
word">import { saveAs } word">from 'file-saver'
word">import { Loading, Message } word">from 'element-ui';
word">export word">default ({ store }, inject) => {word">const zip = (url, name) => {word">let loadingInstance = Loading.service({lock: true,text: '正在下载...',spinner: 'el-icon-loading',background: 'rgba(0, 0, 0, 0.7)'});word">const fullUrl = '/prod-api' + url;axios({method: 'get',url: fullUrl,responseType: 'blob',timeout: 600000,headers: { 'Authorization': store.state.token }}).then(word">async (res) => {word">const isLogin = word">await blobValidate(res.data);loadingInstance.close();word">if (isLogin) {word">const blob = word">new Blob([res.data], { type: 'application/zip' })saveAs(blob, name)} word">else {printErrMsg(res.data);}}).catch(() => {loadingInstance.close();});};// 验证是否为blob格式word">async word">function blobValidate(data) {word">try {word">const text = word">await data.text();JSON.parse(text);word">return false;} word">catch (error) {word">return true;}}word">let errorCode = {'401': '认证失败,无法访问系统资源','403': '当前操作没有权限','404': '访问资源不存在','default': '系统未知错误,请反馈给管理员'}word">async word">function printErrMsg(data) {word">const resText = word">await data.text();word">const rspObj = JSON.parse(resText);word">const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']Message.error(errMsg);}// 注入到全局上下文中inject('downloadZip', {zip,});
}

http://www.ppmy.cn/news/1539646.html

相关文章

利用python实现把视频转换成gif图形

将视频转换为 GIF 图形的重要性不言而喻。在信息快速传播和多种社交平台广泛应用的背景下&#xff0c;GIF 动画不仅为个人用户提供了一种轻松的表达方式&#xff0c;也为商业营销和品牌推广创造了巨大的价值。随着技术的发展&#xff0c;GIF 的创作和应用将更加广泛&#xff0c…

装饰器模式知识分享:Android (Kotlin) 与 iOS (Swift) 实现

装饰器模式&#xff08;Decorator Pattern&#xff09;是一种非常重要的设计模式&#xff0c;它允许我们在不修改已有对象的情况下&#xff0c;动态地为其添加新的行为和功能。 这种模式广泛用于 Android 和 iOS 的开发中&#xff0c;特别是在我们想要扩展现有功能&#xff0c;…

网络七层架构

目录标题 网络七层架构从正确认识网络七层架构开始 网络七层架构 简介&#xff1a; 网络七层架构是指ISO/OSI模型&#xff0c;它是国际标准化组织&#xff08;ISO&#xff09;制定的一种用于计算机网络体系结构的参考模型。该模型将计算机网络的功能划分为七个层次&#xff0c…

windows 导出 oracle DMP文件

1.dba登录oracle sqlplus /orcl as sysdba 2.创建目录 授权目录 create directory bluesys1016 as C:\bluesys\DemoData; grant read,write on directory bluesys1016 to bluesys; 3.退出sqlplus exit 4.执行expdp expdp bluesys/bluesysorcl directorybluesys1016 dumpfil…

阿里 C++面试,算法题没做出来,,,

我本人是非科班学 C 后端和嵌入式的。在我面试的过程中&#xff0c;竟然得到了阿里​ C 研发工程师的面试机会。因为&#xff0c;阿里主要是用 Java 比较多&#xff0c;C 的岗位比较少​&#xff0c;所以感觉这个机会还是挺难得的。 阿里 C 研发工程师面试考了我一道类似于快速…

linux通过configfs方式开启uvc、uac、adb等功能

linux通过configfs方式开启uvc、uac、adb等功能 IamGroot2023 已于 2023-03-22 13:02:02 修改 阅读量3.1k 收藏 20 点赞数 3 文章标签&#xff1a; adb linux android Powered by 金山文档 版权 setusbconfig uvc&#xff1a;开启uvc功能。 切换到usb device模式&#xff1a; …

如何安装和使用 Git Large File Storage (LFS)

在现代软件开发中&#xff0c;我们经常需要处理大型文件&#xff0c;如图像、音频、视频或二进制文件。Git 在处理这些大文件时可能会遇到性能问题&#xff0c;因为 Git 会存储文件的每一个版本。为了解决这个问题&#xff0c;Git Large File Storage (LFS) 应运而生。Git LFS …

ros2 action相关

ros2 action相关 总体代码参考&#xff1a; 一定要先看这里的示例&#xff0c;后续是对这个示例的说明补充 重点关注execute中&#xff0c;思考action的客户端与服务端联动过程中需要的是&#xff0c;任务执行的一些状态信息交互&#xff0c;就能明补execute为什么这样写了 代…