vue中利用element UI實現(xiàn)文件上傳

項目中經(jīng)常會用到文件上傳的功能叔收,為避免重復犯錯啸驯,現(xiàn)將近階段親測過的方法,記錄下

  • 首先后端接口需求英上,需同時傳文件FormData和其他所需參數(shù)炭序,如下圖所示:
    文件上傳接口.png
  • 前端簡單的配置界面,如圖所示苍日,利elementUI組件el-upload
    前端界面設置.png
  • 實現(xiàn)方法

關鍵點:el-uploadhttp-request方法獲取文件File信息和FormData方式傳參

1.利用http-request函數(shù)獲取上傳的文件File信息

http-request主要為覆蓋默認的上傳行為惭聂,可以自定義上傳的實現(xiàn),因需要實現(xiàn)手動上傳相恃,故應用到此方法

<template></template>

<template>
  <el-upload
    class="upload-demo"
    ref="upload"
    accept=".dat"
    action=""
    :http-request="httpRequest"
    :auto-upload="false"
    :file-list="fileList"
    :on-change="handleFileChange"
  >
    <el-button slot="trigger" size="small" type="success">選取文件</el-button>
    <div slot="tip" class="el-upload__tip" style="color: #ee4234">
      {{ tips }}
    </div>
  </el-upload>
</template>

手動上傳時辜纲,會觸發(fā)http-request的回調(diào)函數(shù)httpRequest

httpRequest方法

httpRequest(param) {
      let fileObj = param.file; // 相當于input里取得的files
      let fileName = fileObj.name;
      let formData = new FormData(); // FormData 對象
      formData.append("MultipartFile", fileObj); // 文件對象
      formData.append("fileCreateName", fileName);//傳遞其他參數(shù)
      this.$emit("upload", formData);
 }

2.利用axiopost方法,實現(xiàn)與后端接口聯(lián)調(diào)

關鍵點:設置headersmultipart/form-data

注意:uploadFile方法為封裝好的方法

//文件上傳
export function uploadFile(formData) {
  return request({
    url: '/dataFileRecord/add',
    method: 'post',
    data: formData,
    isFormData: true,
    headers: {
      'Content-Type': 'multipart/form-data'
    }
  })
}

3.完整代碼拦耐,包括判斷上傳文件格式每次切換文件只顯示最新選擇的一個

自己封裝的Upload組件

<template>
  <el-upload
    class="upload-demo"
    ref="upload"
    accept=".dat"
    action=""
    :http-request="httpRequest"
    :auto-upload="false"
    :file-list="fileList"
    :on-change="handleFileChange"
  >
    <el-button slot="trigger" size="small" type="success">選取文件</el-button>
    <div slot="tip" class="el-upload__tip" style="color: #ee4234">
      {{ tips }}
    </div>
  </el-upload>
</template>
<script>
export default {
  name: "upload",
  data() {
    return {
      tips: "只能上傳dat格式的文件",
      fileList: [],
    };
  },
  props: ["fileName"],
  methods: {
    init() {
      this.fileList = [];
      this.tips = "只能上傳dat格式的文件";
    },
    httpRequest(param) {
      let fileObj = param.file; // 相當于input里取得的files
      let fileName = fileObj.name;
      let formData = new FormData(); // FormData 對象
      formData.append("MultipartFile", fileObj); // 文件對象
      formData.append("fileCreateName", fileName);
      this.$emit("upload", formData);
    },
    isFormatValid(type) {
      let pStrDAt = /\.dat?$/i;
      return pStrDAt.test(type);
    },
    handleFileChange(file, fileList) {
      this.beforeUpload(file);
      if (fileList.length > 0) {
        this.fileList = [fileList[fileList.length - 1]]; // 這一步耕腾,是 展示最后一次選擇的dat文件
      }
    },
    beforeUpload(file) {
      let fileName = file.name;
      this.$emit("update:fileName", fileName);
      let isDat = this.isFormatValid(fileName);
      if (!isDat) {
        this.tips = "當前選擇的文件格式不正確,請重新選擇杀糯!";
      } else {
        this.tips = "";
      }
      return isDat;
    },
    handleSubmit() {
      if (!this.tips) {
        this.$refs.upload.submit();
      }
    },
  },
};
</script>
<style lang="scss" scoped>
.el-upload__tip {
  color: #ee4234;
  position: absolute;
  top: 40px;
}
</style>

注意:點擊確定按鈕扫俺,調(diào)用組件uploadsubmit方法,從而觸發(fā)httpRequest方法固翰,實現(xiàn)手動上傳

 this.$refs.upload.submit();

主頁面

<template>
  <MainPanel
    ref="panel"
    :tableInfo="tableInfo"
    :dialogInfo="dialogInfo"
    @table-update="handlePageUpdate"
    @table-edit="handleTableEdit"
    @table-delete="handleTableDelete"
    @btn-search="handleSearch"
    @btn-add="handleAdd"
    @btn-batch-delete="handleBatchDelete"
    @dialog-confirm="handleDialogConfirm"
    @dialog-cancel="handleDialogCancel"
  >
    <el-col :span="1" class="search-text">文件名稱:</el-col>
    <el-col :span="3">
      <el-input
        v-model="searchFileName"
        placeholder="請輸入文件名稱"
        style="width: 100%"
        clearable
      ></el-input>
    </el-col>
    <template #dialog>
      <el-col :span="6">
        <Upload
          v-if="!isEdit"
          ref="upload"
          :fileName.sync="fileName"
          @upload="handleUpload"
        ></Upload>
      </el-col>
    </template>
  </MainPanel>
</template>
<script>
import MainPanel from "@/components/MainPanel";
import { uploadFile, getFileList, updateFile, delFile } from "@/api/api.js";
import Upload from "@/components/Upload";
export default {
  name: "fileManage",
  data() {
    var columns = [
      {
        label: "文件名稱",
        prop: "fileCreateName",
        required: true,
      },
      {
        label: "文件大小",
        prop: "fileSize",
      },
      {
        label: "文件類型",
        prop: "fileType",
      },
      {
        label: "創(chuàng)建時間",
        prop: "createTime",
      },
      {
        label: "更新時間",
        prop: "updateTime",
      },
    ];
    var validateName = (rule, value, callback) => {
      if (!this.dialogInfo.condition.fileCreateName) {
        callback(new Error("文件名不能為空"));
      } else {
        callback();
      }
    };
    return {
      tableInfo: {
        tableData: [],
        columns: columns,
        tableTotal: 0,
        pageInfo: {},
      },
      dialogInfo: {
        title: "文件上傳",
        columns: columns.filter((item) => item.required),
        condition: {
          fileCreateName: "",
        },
        dialogWidth: "50%",
        rules: {
          fileCreateName: [
            { required: true, validator: validateName, trigger: "blur" },
          ],
        },
      },
      isEdit: false,
      condition: {
        pageNo: 1,
        pageSize: 10,
      },
      currentId: "",
      fileName: "",
      searchFileName: "",
    };
  },
  components: { MainPanel, Upload },
  watch: {
    fileName(val) {
      this.dialogInfo.condition.fileCreateName = val;
    },
  },
  mounted() {
    //獲取文件列表
    this.getFileList();
  },
  methods: {
    async getFileList() {
      let pInfo = await getFileList(this.condition);
      this.tableInfo.tableData = pInfo.data.data.content;
      this.tableInfo.tableTotal = pInfo.data.data.totalElements;
    },
    handlePageUpdate(condition) {},
    handleTableEdit(row) {
      this.isEdit = true;
      this.dialogInfo.title = "文件編輯";
      this.currentId = row.id;
    },
    handleTableDelete(row) {
      this.deleteFiles([row.id]);
    },
    handleBatchDelete(items) {
      let idArray = items.map((item) => item.id);
      this.deleteFiles(idArray);
    },
    handleAdd() {
      this.isEdit = false;
      this.dialogInfo.condition.fileCreateName = "";
      if (this.$refs.upload) {
        this.$refs.upload.init();
      }
    },
    handleSearch() {
      this.tableInfo.pageInfo = {
        pageNo: 1,
        pageSize: 10,
      };
      this.condition.pageNo = 1;
      this.condition.pageSize = 10;
      this.condition.param = JSON.stringify({
        fileCreateName: this.searchFileName,
      });
      this.getFileList();
    },
    handleDialogConfirm() {
      if (this.isEdit) {
        this.updateFile();
      } else {
        if (this.$refs.upload) {
          this.$refs.upload.handleSubmit();
        }
      }
    },
    handleDialogCancel() {
      this.fileName = "";
    },
    addFile(formData) {
      uploadFile(formData).then((res) => {
        if (res.data.code === "0") {
          this.handleSuccess("上傳");
        } else {
          this.handleError("上傳");
        }
      });
    },
    updateFile() {
      updateFile({
        fileCreateName: this.dialogInfo.condition.fileCreateName,
        id: this.currentId,
      }).then((res) => {
        if (res.data.code === "0") {
          this.handleSuccess("更新");
        } else {
          this.handleError("更新");
        }
      });
    },
    deleteFiles(idArray) {
      delFile(idArray).then((res) => {
        if (res.data.code === "0") {
          this.handleSuccess("刪除");
        } else {
          this.handleError("刪除");
        }
      });
    },
    handleUpload(formData) {
      this.addFile(formData);
    },
    handleSuccess(type) {
      this.$message({
        type: "success",
        message: "文件" + type + "成功狼纬!",
      });
      if (this.$refs.panel) {
        this.$refs.panel.init();
      }
      this.fileName = "";
      this.getFileList();
    },
    handleError(type) {
      this.$message({
        type: "error",
        message: "文件" + type + "失敗羹呵,請檢查服務連接!",
      });
    },
  },
};
</script>
<style lang="scss" scoped>
</style>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末畸颅,一起剝皮案震驚了整個濱河市担巩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌没炒,老刑警劉巖涛癌,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異送火,居然都是意外死亡拳话,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門种吸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弃衍,“玉大人,你說我怎么就攤上這事坚俗【刀ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵猖败,是天一觀的道長速缆。 經(jīng)常有香客問我,道長恩闻,這世上最難降的妖魔是什么艺糜? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮幢尚,結(jié)果婚禮上破停,老公的妹妹穿的比我還像新娘。我一直安慰自己尉剩,他們只是感情好真慢,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著理茎,像睡著了一般晤碘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上功蜓,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音宠蚂,去河邊找鬼式撼。 笑死,一個胖子當著我的面吹牛求厕,可吹牛的內(nèi)容都是我干的著隆。 我是一名探鬼主播扰楼,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼美浦!你這毒婦竟也來了弦赖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤浦辨,失蹤者是張志新(化名)和其女友劉穎蹬竖,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體流酬,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡币厕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了芽腾。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片旦装。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖摊滔,靈堂內(nèi)的尸體忽然破棺而出阴绢,到底是詐尸還是另有隱情,我是刑警寧澤艰躺,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布呻袭,位于F島的核電站,受9級特大地震影響描滔,放射性物質(zhì)發(fā)生泄漏棒妨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一含长、第九天 我趴在偏房一處隱蔽的房頂上張望券腔。 院中可真熱鬧,春花似錦拘泞、人聲如沸纷纫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽辱魁。三九已至,卻和暖如春诗鸭,著一層夾襖步出監(jiān)牢的瞬間染簇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工强岸, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留锻弓,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓蝌箍,卻偏偏與公主長得像青灼,于是被迫代替她去往敵國和親暴心。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容