Vue combat--vue+elementUI realizes multi-file upload + preview (word/PDF/picture/docx/doc/xlxs/txt)

need

    Recently, I encountered a requirement in the project of vue2.0+element UI: the requirement is to realize the online preview function of files while uploading multiple files. The demand diagram is as follows:
insert image description here
insert image description here

    Seeing this demand, Xiao Li's head exploded. I don't know how to start, and I haven't encountered similar functions in previous practical projects. Therefore, it took a lot of effort to realize such a function.
    First of all, check the official documents of elemnt UI and find that most of the functions that realize the effect of file upload can provide a preview function, but the style and content of the function cannot be specified, which has certain limitations
    . PDF preview, word preview and other keywords", and found that most of the big guys' methods realized image preview, but did not realize multiple file uploads (maybe because I did not find related functions).
    Therefore, Xiaoli decided to encapsulate this function by himself, and hoped that some friends could adjust and optimize it on the basis of this. Looking forward to your participation~~
    Not much to say, let’s talk about talent

Realize requirements

1. Use on-preview+window.open() to realize the simple preview effect

    After checking the element UI document, I found that there is an Attribute in el-upload called on-preview (the hook when clicking the uploaded file in the file list) which is specially used for file preview. Click on the file to start the function. Combined with the window.open() method, you can directly complete the viewing file
    code of a newly opened window page as follows:

  • HTML part
//on-preview="Previewf"是必须的也是预览的关键
 <el-upload
           class="upload-demo"
           :action="uploadUrl"
           :on-success="handlePreview"
           :on-remove="handleRemove"
           :before-upload="beforeUpload"
           :on-preview="Previewf"
           multiple
           :limit="5"
           :on-exceed="handleExceed"
           :file-list="file-list"
           :accept="accepts"
         >
           <el-button icon="el-icon-upload2" @click="uploadFileClick($event)"
             >上传文件</el-button
           >
         </el-upload>
  • methods section
Previewf(file) {
    
    
      console.log(file);
      // window.open(file.response)
      if (file) {
    
    
        const addTypeArray = file.name.split(".");
        const addType = addTypeArray[addTypeArray.length - 1];
        console.log(addType);
        if (addType === "pdf") {
    
    
          let routeData = this.$router.resolve({
    
    
            path: "/insurancePdf",
            query: {
    
     url: file.response, showBack: false },
          });
          window.open(routeData.href, "_blank");
        }
        //".rar, .zip, .doc, .docx, .xls, .txt, .pdf, .jpg,  .png, .jpeg,"
        else if (addType === "doc" || addType === "docx" || addType === "xls") {
    
    
          window.open(
            "http://view.officeapps.live.com/op/view.aspx?src=" + file.response
          );
        } else if (addType === "txt") {
    
    
          window.open(file.response);
        } else if (["png", "jpg", "jpeg"].includes(addType)) {
    
    
          window.open(file.response);
        } else if (addType === "rar" || addType === "zip") {
    
    
          this.$message({
    
    
            message: "该文件类型暂不支持预览",
            type: "warning",
          });
           return false;
        }
      }
    },
  • Function preview
    insert image description here
        Click the blue file part to open a new page. This simple use of element UI completes this function~ Do you think it is not so difficult?

2. Encapsulate components to achieve more complete upload completion and preview functions

    The above functions can complete the preview, but some of them are inconsistent with our needs and cannot fully meet my business needs. Therefore, on the basis of element UI, I have packaged components to complete the following functions: Not much to
insert image description here
    say , or the code:

  • HTML part
/*
重点关注的代码:
	:show-file-list="false"
	ref="contentWrap
*/
 <el-upload
            class="upload-demo"
            ref="uploadCom"
            :show-file-list="false"
            :action="uploadUrl"
            :on-success="onSuccess"
            :on-remove="handleRemove"
            :before-upload="beforeUpload"
            multiple
            :limit="5"
            :on-exceed="handleExceed"
            :file-list="file-list"
            :accept="accepts"
          >
            <el-button icon="el-icon-upload2" @click="uploadFileClick($event)"
              >将文件拖到此处,或<em>点击上传</em></el-button
            >
            <div slot="tip" class="el-upload__tip">
              支持扩展名:.rar .zip .doc .docx .xls .txt .pdf .jpg .png .jpeg,最多上传5个文件,每个大小不超过50Mb
            </div>
          </el-upload>
          <div class="flex mt20" v-if="file-list.length > 0">
                <div
                  class="items-wrap"
                  ref="contentWrap"
                  :style="wrapHeight <= 70 ? 'height: auto' : `height: 60px;`"
                  :class="{ noHidden: noHidden }"
                >
                  <uploadfile-item
                    v-for="(item, index) in file-list"
                    :key="index"
                    :file="item"
                    @cancel="cancelFile"
                    :showDel="true"
                    class="mr20"
                  ></uploadfile-item>
                </div>
                <div
                  class="on-off"
                  v-if="wrapHeight > 70"
                  @click="noHidden = !noHidden"
                >
                  {
   
   { noHidden ? "收起" : "更多" }}
                </div>
              </div>
  • methods section
import UploadfileItem from "";
export default {
    
    
  components: {
    
    
    UploadfileItem,
  },
  data() {
    
    
    return {
    
    
      noHidden: true,
      wrapHeight: 0,
      delDialogitem: 0,
      imgLoad: false,
      centerDialogVisible: false,
     file-list:[],
      },
    };
  },
  methods: {
    
    
    cancelFile(file) {
    
    
      console.log(file);
    },

    // 上传文件只能添加五条
    uploadFileClick(event) {
    
    
      if (this.formLabelAlign.annex.length === 5) {
    
    
        this.$message({
    
    
          type: "warning",
          message: "最多只可以添加五条",
        });
        event.stopPropagation();
        return false;
      }
    },
    //
    onSuccess(response, file, annex) {
    
    
      if (!response) {
    
    
        this.$message.error("文件上传失败");
      } else {
    
    
        this.imgLoad = false;
        this.$message({
    
    
          message: "上传成功!",
          type: "success",
        });
      }
    },
   
    beforeUpload(file) {
    
    
     console.log(file);
    },
    handleExceed(files, ) {
    
    
 		console.log(file);
  },
};
  • UploadfileItem component content
<template>
  <div class="file-style-box">
    <div class='upload-file-item'>
      <img :src="imgsrc[getEnd(file.fileName)]" alt="">
      <div>
        <p class='file-name'>
          <span class='name'>{
    
    {
    
    file.fileName}}</span>
          </p>
        <div class='option'>
          <span class='size'>{
    
    {
    
    file.size | toKB}}kb</span>
          <div>
            <span v-if='showDel && (isPdf(file) || isImg(file))' @click='previewHandler(file.url)' class='preview mr10'>预览</span>
            <a v-if='!showDel' @click='downLoadHandler' class='preview' :href="file.url">下载</a>
            <span v-if='showDel' class='mr10 success'>上传完成</span>
          </div>
        </div>
        <div class='delBtn' v-if='showDel' @click='cancelHanlder(file)'>
          <img src="@/assets/public/tips-err.png" alt="">
        </div>
      </div>
    </div>
    <el-dialog
      title="图片预览"
      width="800px"
      class="imgDlgBox"
      :visible.sync="imgDlgVisible"
      :close-on-click-modal="true"
      :modal="false"
      append-to-body
    >
      <img :src="imgUrl" alt="">
    </el-dialog>
  </div>

</template>

<script>
export default {
    
    
  props: {
    
    
    file: {
    
    
      type: Object,
      default: {
    
    }
    },
    showDel: {
    
    
      type: Boolean,
      default: false
    }
  },
  data() {
    
    
    return {
    
    
      imgDlgVisible: false,
      imgUrl: '',
      pdfUrl: '',
      imgsrc: {
    
    
      /*
		*imgsrc 是关于内部静态图片的显示的路径,需要自己设置
		*示例"xls": require('@/assets/image/xls.png'),
		xis的文件所需要加载的路径是;assets文件下的image文件夹下的xls.png
	*/
        "rar": require('@'),
        "zip": require('@'),
        "pdf": require('@'),
        "jpg": require('@'),
        "jpeg": require('@'),
        "png": require('@'),
        "doc": require('@'),
        "docx": require('@'),
        "txt": require('@'),
        "xls": require('@/assets/image/xls.png'),
      }
    }
  },
  filters: {
    
    
    toKB(val) {
    
    
      return (Number(val) / 1024).toFixed(0);
    }
  },
  methods: {
    
    
    cancelHanlder(item) {
    
    
      this.$emit('cancel', item)
    },
    previewHandler(data) {
    
    
      if (data) {
    
    
        const addTypeArray = data.split(".");
        const addType = addTypeArray[addTypeArray.length - 1];
        if (addType === "pdf") {
    
    
          let routeData = this.$router.resolve({
    
     path: "/insurancePdf", query: {
    
     url: data, showBack: false } });
          window.open(routeData.href, '_blank');
        } else if (addType === "doc") {
    
    
          window.open(
            `https://view.officeapps.live.com/op/view.aspx?src=${
      
      data}`
          );
        } else if (addType === "txt") {
    
    
          window.open(`${
      
      data}`);
        } else if (['png','jpg','jpeg'].includes(addType)) {
    
     // 图片类型
          this.imgDlgVisible = true
          this.imgUrl = data
        }
      }
    },
}
</script>
<style lang='scss'>
.file-style-box {
    
    
  padding: 10px 10px 0 0;
}
.imgDlgBox {
    
    
  .el-dialog {
    
    
    .el-dialog__body {
    
    
      text-align: center;
      img {
    
    
        width: 700px;
        height: auto;
      }
    }
  }
}
.upload-file-item {
    
    
  background: #FAFAFA;
  border-radius: 4px;
  padding: 5px 10px;
  margin-bottom: 10px;
  display: flex;
  font-size: 14px;
  width: 236px;
  box-sizing: border-box;
  position: relative;
  img {
    
    
    width: 32px;
    height: 40px;
    margin-top: 5px;
    margin-right: 10px;
  }
  .option {
    
    
    display: flex;
    align-items: center;
    justify-content: space-between;
  }
  .file-name {
    
    
    width: 163px;
    display: flex;
    flex-wrap: nowrap;
    font-size: 14px;
    color: #333;
    font-weight: 400;
    .name {
    
    
      white-space: nowrap;
      text-overflow: ellipsis;
      overflow: hidden;
    }
    .end {
    
    
      flex: 0 0 auto;
    }
    .el-button{
    
    
      border: none;
      padding: 0px;
      width: 90%;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
  }
  .size {
    
    
    color: #969696;
  }
  .success {
    
    
    color: #78C06E;
  }
  .delBtn {
    
    
    position: absolute;
    top: -14px;
    right: -18px;
    cursor: pointer;
    img {
    
    
      width:16px;
      height:16px
    }
  }
  // .del {
    
    
  //   color: #E1251B;
  //   cursor: pointer;
  // }
  .preview {
    
    
    color: #0286DF;
    cursor: pointer;
  }
  .mr10 {
    
    
    margin-right: 10px;
  }
}
</style>
  • renderings
    insert image description here
    insert image description here

    The above can achieve multi-file upload + preview (word/PDF/picture/docx/doc/xlxs/txt), I hope this implementation method will also help you

    If it is helpful, please don't forget to like, comment, interact and pay attention~

Add answers to more questions asked in the comment area

1. imgsrc path

imgsrc: {
    
    
"rar": require('@/assets/material/zip.png'),
}
这个位置会报错

    An error is reported here because the content here is a static resource. It is some details of our preview image, which grows as shown in the following figure:
insert image description hereinsert image description here

    You should also need to configure the path of such a folder locally.

2. Display the upload style of the original elementui

重点关注el- upload的代码
:show-file-list="false" //关闭原来的上传样式
ref="contentWrap //这个是通过父子组件传值将子组件的页面

3. file.response shows that there is no such attribute and method

    file.response是element UI的内置的组件的方法,引入element UI使用文件上传组件就可以实现
    我之前写这儿的file.response 时候,有一个传递值也有问题,好像是element UI的钩子函数的问题,你先打印file。然后看是不是file.response ,不是的话 查看一下file的其他属性,有一个是跟回调相关的返回值
    就可以解决啦

4. https://view.officeapps.live.com/op/view.aspx?src=${data}What is it for? Do I need to install other plug-ins to preview PDF?

	首先:不需要再安装其他预览资源加载包,所有的预览都是通过windom.open()方法打开一个新窗口预览。
	PDF的预览时使用的office官方的接口文档:`https://view.officeapps.live.com/op/view.aspx?src=${
    
    data}就可以预览PDF文档了。
	图片的预览是通过dialog的弹窗实现的,就简单一个弹窗
	rar和zip不支持预览,只能下载查看

    If it is helpful, please don't forget to like, comment, interact and pay attention~

Guess you like

Origin blog.csdn.net/m0_62209297/article/details/125208566