vue+elementUI實現多文件上傳與預覽功能實戰記錄(word/PDF/圖片/docx/doc/xlxs/txt)

需求

最近在做vue2.0+element UI的項目中遇到瞭一個需求:需求是多個文件上傳的同時實現文件的在線預覽功能。需求圖如下:

看到這個需求的時候,小栗腦袋一炸。並不知道該如何下手,之前的實踐項目中也並沒有遇到相似的功能。因此也廢瞭一番功夫想要實現這樣一個功能。

首先先查看elemnt UI的官方文檔發現,大部分的實現文件上傳效果的功能,即使可以提供預覽的功能,但是不能指定該功能的樣式和內容有一定的局限性

然後小栗查找“多文件上傳預覽、PDF預覽、word預覽等關鍵詞”,發現大部分的大佬的方法都是實現瞭圖片預覽,並沒有實現多文件上傳(也可能是因為我並沒有找到相關的功能)。

因此小栗決定自己封裝這個功能,並希望有朋友能在這個的基礎上進行調整優化。期待你們的參與哦~~

話不多說,上才藝

實現需求

1、利用on-preview+window.open()實現簡易版預覽效果

查看element UI文檔後發現el-upload裡面有一個Attribute叫on-preview( 點擊文件列表中已上傳的文件時的鉤子)是專門用來做文件預覽的。點擊文件就可以出發該函數。再結合window.open()方法可以直接完成一個新開窗口頁的查看文件

代碼如下:

HTML部分

//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部分

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;
        }
      }
    },

功能預覽

點擊藍色的文件部分就可以出現新開頁面,這個簡易的利用element UI就完成瞭這個功能啦~有沒有覺得還是不那麼難呢?

2、封裝組件實現更完整的上傳完成、預覽功能

上述的功能可以完成預覽,但與我們的需求有一部分的出入,不能夠完全滿足我的業務需求,因此在element UI的基礎上,我進行瞭組件封裝,以求完成以下功能:

話不多說,還是上代碼:

HTML部分

/*
重點關註的代碼:
	: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部分

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組件內容

<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" rel="external nofollow" >下載</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>

效果圖

以上就可以實現實現多文件上傳+預覽(word/PDF/圖片/docx/doc/xlxs/txt)啦,希望這樣的實現方式也對你有幫助哦

追加關於問的比較多的問題回復

1、imgsrc路徑

imgsrc: {
"rar": require('@/assets/material/zip.png'),
}
這個位置會報錯

這裡報錯是因為此處的內容是靜態資源,他是我們預覽圖片的一些細節,長成如下圖所示:

你本地應該也需要配置這樣一個文件夾的路徑就可以啦。

2、顯示原本elementui的那個上傳樣式

重點關註el- upload的代碼
:show-file-list="false" //關閉原來的上傳樣式
ref="contentWrap //這個是通過父子組件傳值將子組件的頁面

3、file.response顯示沒有這個屬性和方法

    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}是幹嘛的?預覽PDF需要安裝其他的插件嗎?

    首先:不需要再安裝其他預覽資源加載包,所有的預覽都是通過windom.open()方法打開一個新窗口預覽。
    PDF的預覽時使用的office官方的接口文檔:`https://view.officeapps.live.com/op/view.aspx?src=${data}就可以預覽PDF文檔瞭。
    圖片的預覽是通過dialog的彈窗實現的,就簡單一個彈窗
    rar和zip不支持預覽,隻能下載查看

總結

到此這篇關於vue+elementUI實現多文件上傳與預覽功能(word/PDF/圖片/docx/doc/xlxs/txt)的文章就介紹到這瞭,更多相關vue+elementUI多文件上傳預覽內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: