0


vue3+element-plus上传文件,预览文件

vue3+ts+element-plus上传文件,预览文件

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

场景:使用element-plus的el-upload标签,手动上传文件,可预览docx,xlsx,pdf,jpg,jpeg,png(本地资源以及网络资源)。

1、使用el-upload标签

在这里插入图片描述

检查上传文件的文件格式与大小

在这里插入图片描述

上传的附件信息在fileList中,组装接口所需数据进行上传

使用docx-preview插件预览docx类型的文件

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

使用xlsx插件预览xlsx文件

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里遇到了问题,引入xlsx插件的时候出现"export ‘default’ (imported as ‘XLSX’) was not found in 'xlsx’报错
解决:

直接将import XLSX from 'xlsx’改为import * as XLSX from 'xlsx/xlsx.mjs’即可

图片预览

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

pdf预览

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

完整代码

<template><el-dialog
    v-model="uploadDialogVisible"
    title="上传"
    width="800px"
    label-width="100px"@close="uploadDialogVisible = false"><el-upload
      ref="uploadRef"
      v-model:file-list="fileList"class="upload-demo"
      drag
      :multiple="true":auto-upload="false":accept="props.allowType":limit="props.limit":before-upload="beforeAvatarUpload":on-preview="previewFun"><el-icon class="el-icon--upload"><upload-filled /></el-icon><div class="el-upload__text"><em>选择文件</em></div><template #tip><div class="el-upload__tip">
          支持格式:{{ props.allowType }};限制大小{{ props.size }}M</div></template></el-upload><template #footer><span class="dialog-footer"><el-button round @click="cancelFun">取消</el-button><el-button round type="primary"@click="submitFun">确定</el-button><el-button round type="primary"@click="getFileList">获取文件</el-button
        ></span></template></el-dialog><!-- 查看 --><viewer ref="fileViewerRef":dialog-doc="dialogDoc"/></template><script setup lang="ts">/* eslint-disable */import{ defineProps, defineEmits, ref, reactive, computed }from"vue";importtype{
  FormInstance,
  UploadProps,
  UploadUserFile,
  UploadRawFile
}from"element-plus";import{ ElMessage }from"element-plus";import{ UploadFilled }from"@element-plus/icons-vue";import{ api }from"@/api";import SparkMD5 from"spark-md5";import Viewer from"./viewer.vue";interfaceProps{
  uploadDialogVisible?:boolean;
  allowType?:string;
  limit?:number;
  fileList?:any;
  size?:number;
  fileExtendId?:string;
  fileCategory?:number;
  folderName?:string;
  systemSource?:string;
  uploadUrl?:string;}//propsconst props:any=withDefaults(defineProps<Props>(),{
  uploadDialogVisible:false,
  allowType:"doc,docx,jpg,jpeg,png,xlsx,pdf",
  limit:5,
  size:5,
  fileExtendId:"",
  fileCategory:2,
  folderName:"ceshi",
  systemSource:"ceshi",
  uploadUrl:"http://192.168.188.3:7001"});const uploadDialogVisible =computed(()=>{return props.uploadDialogVisible;});const uploadRef =ref<FormInstance>();const fileList =ref(([]asany));const fileExtendId =ref("682D0E35121A4D4E831714CDACD5A18E");constbeforeAvatarUpload=()=>{const flag =ref(true);
  fileList.value.forEach((item:any)=>{console.log(item);const type = item.name.split(".")[1];if(props.allowType.indexOf(type)==-1){ElMessage({
        type:"error",
        message:`格式错误,支持格式:${props.allowType}!`});
      flag.value =false;return;}elseif(item.size /1024/1024> props.size){
      ElMessage.error(`文件最大${props.size}MB!`);
      flag.value =false;return;}});return flag.value;};//取消constcancelFun=()=>{emit("cancel",false);};constsubmitFun=(formEl: FormInstance |undefined)=>{// 判断是否有文件需要上传if(fileList.value.length){const flag =beforeAvatarUpload();if(!flag){return;}// 组合数据const params =newFormData();const fileConfigs:any=[];if(fileList.value.length){
      fileList.value.forEach((item:any, index:number)=>{// 判断一下是不是新上传的if(item.id){
          fileConfigs.push({
            fileId: item.id,
            fileName: item.name,
            sort:++index,// 必须从1开始,依次12345往下
            md5:""});}else{
          params.append("file", item.raw);const spark =newSparkMD5.ArrayBuffer();
          spark.append(item.raw);const md5 = spark.end();
          fileConfigs.push({
            fileId:"",
            fileName: item.name,
            sort:++index,// 必须从1开始,依次12345往下
            md5: md5
          });};});}
    params.append("fileExtendId", fileExtendId.value);
    params.append("fileCategory", props.fileCategory);
    params.append("folderName", props.folderName);
    params.append("systemSource", props.systemSource);
    params.append("FileConfigs",JSON.stringify(fileConfigs));console.log(params);
    api.adminCenter.UploadFiles(params).then((res:any)=>{if(res.status.code ==200){
        fileExtendId.value = res.result.fileExtendId;// 拿到了组合id,继续做业务}});}else{console.log("直接做业务");}};// 获取附件constgetFileList=()=>{
  api.adminCenter
    .GetFileList({
      fileExtendIds: fileExtendId.value
    }).then((res:any)=>{if(res.status.code ==200){
        res.result.forEach((ele:any)=>{
          ele.name = ele.fileOldName;
          fileList.value.push(ele);});}else{}});};let dialogDoc:any=ref(false);const fileViewerRef =ref<any>(null);constpreviewFun=(file:any)=>{console.log(file.halfPath);
  dialogDoc.value =true;let data = file;// 上传过的文件组成完成的网络路径if(file.halfPath){
    data.src =`${props.uploadUrl}${file.halfPath}`;}const suffix = data.name.split(".")[1];if(suffix =="docx"){
    fileViewerRef.value?.viewDocx(data);}elseif(suffix =="xlsx"){
    fileViewerRef.value?.viewXlsx(data);}elseif(suffix =="jpg"|| suffix =="jpeg"|| suffix =="png"){
    fileViewerRef.value?.viewImg(data);}elseif(suffix =="pdf"){
    fileViewerRef.value?.viewPdf(data);}};// 声明emitconst emit =defineEmits(["cancel"]);</script>
<template><!-- doc --><el-dialog
    v-model="dialogDocxValue":title="dialogTitle"
    width="80%"@close="dialogDocxClose"><div ref="docxRef"class="word-div"></div></el-dialog><!-- xlsx --><el-dialog
    v-model="dialogXlsxValue":title="dialogTitle"
    width="80%"@close="dialogXlsxClose"><div ref="xlsxRef"class="xlsx-div"><el-tabs v-model="activeName" type="border-card"><el-tab-pane
          v-for="(item, index) in excelSheet":key="index":label="item.name":name="item.name"><div class="table" v-html="item.html"></div></el-tab-pane></el-tabs></div></el-dialog><!-- 图片 --><el-dialog
    v-model="dialogImgValue":title="dialogTitle"
    width="80%"@close="dialogImgClose"><div class="img-div"><el-image :src="fileData.src":alt="fileData.fileOldName"/></div></el-dialog><!-- pdf --><el-dialog
    v-model="dialogPdfValue":title="dialogTitle"
    width="80%"@close="dialogPdfClose"><div class="pdf-div"><iframe
        id="pdfRef":src="iframeUrl"
        frameborder="0"
        style="width: 100%; height: 99%"></iframe></div></el-dialog></template><script setup lang="ts">import axios from"axios";import{ defineProps, ref, reactive, computed, nextTick }from"vue";import{ renderAsync }from"docx-preview";import*asXLSXfrom"xlsx";interfaceProps{
  dialogDocx?:boolean;
  dialogXlsx?:boolean;
  dialogTitle?:string;}const props:any=withDefaults(defineProps<Props>(),{
  dialogDocx:false,
  dialogTitle:"",
  dialogXlsx:false});const dialogDocxValue:any=ref(false);let dialogTitle =computed(()=>{return props.dialogTitle;});const fileHtml =ref("");const docxRef =ref<any>();// doc 文档预览constviewDocx=(data:any)=>{
  docxRef.value ="";
  dialogDocxValue.value =true;console.log(data);if(data.src){// 已上传的文件axios({
      url: data.src,
      method:"get",
      responseType:"blob"}).then((res)=>{console.log(res);if(res.status ==200){const content = res.data;const blob =newBlob([content]);nextTick(()=>{
          dialogDocxValue.value =true;renderAsync(blob, docxRef.value);
          dialogTitle = data.fileOldName || data.name;});}});}else{// 本地文件const blob =newBlob([data.raw]);nextTick(()=>{
      dialogDocxValue.value =true;renderAsync(blob, docxRef.value);
      dialogTitle = data.fileOldName || data.name;});}};const dialogXlsxValue:any=ref(false);const excelSheet:any=ref([]);const activeName =ref("");constdialogDocxClose=()=>{
  dialogDocxValue.value =false;
  docxRef.value ="";};// xlsx 预览constviewXlsx=(data:any)=>{
  dialogXlsxValue.value =true;console.log(data);if(data.src){axios({
      url: data.src,
      method:"get",
      responseType:"blob"}).then((res)=>{console.log(res);if(res.status ==200){const content = res.data;// const blob = new Blob(content);const reader =newFileReader();
        reader.readAsArrayBuffer(content);
        reader.onload=function(loadEvent:any){const arrayBuffer = loadEvent.target["result"];const workbook =XLSX.read(newUint8Array(arrayBuffer),{
            type:"array"});const list =[];const sheetNames = workbook.SheetNames;
          activeName.value = sheetNames[0];for(const p of sheetNames){let html ="";try{
              html =XLSX.utils.sheet_to_html(workbook.Sheets[p]);}catch(e){
              html ="";}const map ={
              name: p,
              html: html
            };
            list.push(map);}
          excelSheet.value = list;
          dialogTitle = data.fileName || data.name;};}});}else{const blob =newBlob([data.raw]);const reader =newFileReader();
    reader.readAsArrayBuffer(blob);
    reader.onload=function(loadEvent:any){const arrayBuffer = loadEvent.target["result"];const workbook =XLSX.read(newUint8Array(arrayBuffer),{
        type:"array"});const list =[];const sheetNames = workbook.SheetNames;
      activeName.value = sheetNames[0];for(const p of sheetNames){let html ="";try{
          html =XLSX.utils.sheet_to_html(workbook.Sheets[p]);}catch(e){
          html ="";}const map ={
          name: p,
          html: html
        };
        list.push(map);}
      excelSheet.value = list;
      dialogTitle = data.fileName || data.name;};}};constdialogXlsxClose=()=>{
  dialogXlsxValue.value =false;
  excelSheet.value ="";
  activeName.value ="";};const fileData:any=ref({});const dialogImgValue:any=ref(false);// 图片预览constviewImg=(data:any)=>{if(data.src){// 已上传的图片
    fileData.value = data;}else{// 本地图片const freader =newFileReader();
    freader.readAsDataURL(data.raw);
    freader.onload=(e:any)=>{
      fileData.value ={
        src: e.target.result,
        id:newDate(),
        fileName: data.fileOldName || data.name
      };};}
  dialogTitle = data.fileOldName || data.name;
  dialogImgValue.value =true;};constdialogImgClose=()=>{
  dialogImgValue.value =false;};const dialogPdfValue:any=ref(false);const iframeUrl:any=ref("");const pdfRef =ref<any>();constviewPdf=(data:any)=>{if(data.src){axios({
      url: data.src,
      method:"get",
      responseType:"blob"}).then((res)=>{if(res.status ==200){// 把文件流转化为url
        iframeUrl.value =URL.createObjectURL(res.data);
        dialogPdfValue.value =true;}});}else{
    iframeUrl.value =URL.createObjectURL(data.raw);
    dialogPdfValue.value =true;}};constdialogPdfClose=()=>{
  dialogPdfValue.value =false;};defineExpose({
  viewDocx,
  viewXlsx,
  viewImg,
  viewPdf
});</script><style scoped lang="scss">.word-div {
  height:calc(70vh);
  overflow: auto;}.xlsx-div {
  height:calc(70vh);
  overflow: auto;}.img-div {
  height:calc(70vh);
  overflow: auto;
  img {
    width:100%;
    height:100%;}}.pdf-div {
  height:calc(70vh);
  overflow: auto;}</style><style lang="scss">.xlsx-div {.table-html-wrap table {
    border-right: 1px solid #fff;
    border-bottom: 1px solid #e8eaec;
    border-collapse: collapse;// margin: auto;}.table-html-wrap table td {
    border-left: 1px solid #e8eaec;
    border-top: 1px solid #e8eaec;
    white-space: wrap;
    text-align: left;
    min-width: 100px;
    padding: 4px;}

  table {
    border-top: 1px solid #ebeef5;
    border-left: 1px solid #ebeef5;
    width:100%;// overflow: auto;

    tr {
      height: 44px;}

    td {
      min-width: 200px;
      max-width: 400px;
      padding: 4px 8px;
      border-right: 1px solid #ebeef5;
      border-bottom: 1px solid #ebeef5;}}.el-tabs--border-card >.el-tabs__content {
    overflow-x: auto;}}</style>
标签: 前端 typescript vue

本文转载自: https://blog.csdn.net/weixin_42255789/article/details/128716185
版权归原作者 人鱼小姐ww 所有, 如有侵权,请联系我们删除。

“vue3+element-plus上传文件,预览文件”的评论:

还没有评论