vue中利用element UI实现文件上传

项目中经常会用到文件上传的功能,为避免重复犯错,现将近阶段亲测过的方法,记录下

  • 首先后端接口需求,需同时传文件FormData和其他所需参数,如下图所示:
    文件上传接口.png
  • 前端简单的配置界面,如图所示,利elementUI组件el-upload
    前端界面设置.png
  • 实现方法

关键点:el-uploadhttp-request方法获取文件File信息和FormData方式传参

1.利用http-request函数获取上传的文件File信息

http-request主要为覆盖默认的上传行为,可以自定义上传的实现,因需要实现手动上传,故应用到此方法

<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>

手动上传时,会触发http-request的回调函数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);//传递其他参数
      this.$emit("upload", formData);
 }

2.利用axiopost方法,实现与后端接口联调

关键点:设置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>

注意:点击确定按钮,调用组件uploadsubmit方法,从而触发httpRequest方法,实现手动上传

 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: "创建时间",
        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>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容