【Vue】基于Element-UI的文件上传与下载

【项目背景】

最近要求做一个Excel表格上传下载的前端页面,第一次学Vue,Element-UI框架真的用起来很方便,封装了各种基础组件,很适合小白入门开发学习。

Element-UI: https://element.eleme.cn/#/zh-CN

最终效果如下,为降低用户上传错误数据的概率,先提供一个下载模板,然后再让用户上传。

【程序结构】

#1-> 文件下载

下载一般分两种情况,一种是去后台请求接口下载数据流的方式,这种情况适用于需要根据用户自定义需求请求数据库的情况,另一种是请求本地文件下载,比如我现在做的这种情况,只是需要给用户提供一个下载的模板文件,是预先定义好的,所以可以直接把文件就放在本地,前端直接请求文件地址下载即可。

预先定义好的模板文件 [template.xlsx] 放在public/template/下。

需要注意的是vue cli 3.0之后取消了原先的static文件夹,所有的静态资源文件可以放在public/下面。

<template></template>

<!-- 下载数据模板 -->
<div class="div-label"><label>上传文件之前请先下载<span style="font-weight: bold">数据模板</span></label></div>
<el-button @click="download" class="el-button-color add-button-box" size="medium" type="primary">
    <i class="el-icon-download el-icon--right"></i>下载数据模板
</el-button>

 <script></script>

通过window.location.href直接请求本地文件地

methods: {
      // 下载本地文件
      download () {
        window.location.href = 'http://localhost:8080/template/template.xlsx'
      }

#2-> 文件上传

限制一次只能上传一个文件,限定只能上传.xlsx结尾的Excel文件,且文件大小不能超过10MB

选择手动触发上传,并通过:http-request自定义上传方式,让用户先选择一个文件,前端展示上传文件列表,可以选择删除,再让用户确认上传文件,注意这里其实有两个步骤,分别绑定了两个button。

<template></template>

<!-- 上传文件 -->
<div class="div-label"><label>上传文件,仅支持<span style="font-weight: bold">.xlsx</span>格式的Excel文件,且大小不超过<span
        style="font-weight: bold;color: red">10MB</span></label></div>
<el-upload
    class="upload-demo"
    ref="upload"
    action
    accept=".xlsx"
    :limit="1"
    :file-list="fileList"
    :auto-upload="false"
    :on-exceed="handleExceed"
    :on-preview="handlePreview"
    :on-change="handleChange"
    :on-remove="handleRemove"
    :before-upload="beforeUpload"
    :http-request="httpRequest"
    :on-success="handleSuccess"
    :on-error="handleError">
    <el-button slot="trigger" size="medium" type="primary">选取文件</el-button>
    <el-button style="margin-left: 10px;" size="medium" type="success" @click="submitUpload">上传到服务器</el-button>
</el-upload>

<script></script>

文件上传的基础响应事件,具体可参考官方文档

      // 超过文件上传最大个数
      handleExceed (files, fileList) {
        this.$message.warning('很抱歉当前支持最大上传文件个数为 1 个!')
      },
      // 文件上传到服务器之前的文件校验
      beforeUpload (file) {
        const extension = file.name.substring(file.name.lastIndexOf('.') + 1)
        const size = file.size / 1024 / 1024
        if (extension !== 'xlsx') { // 校验文件格式
          this.$message.warning('只支持上传后缀名为.xlsx的Excel文件')
        }
        if (size > 10) { // 校验文件大小
          this.$message.warning('文件大小不能超过10MB')
        }
      },
      // 文件状态改变
      handleChange (file, fileList) {
        if (file) {
          this.fileList = fileList.slice(-3)
        }
      },
      // 文件删除时
      handleRemove (file, fileList) {
        console.log(file, fileList)
        this.fileList = [] // 文件列表置空
      },
      // 点击文件列表中已上传的文件时的钩子
      handlePreview (file) {
        console.log(file)
      },
      // 文件上传成功
      handleSuccess (response, file, fileList) {
        console.log('-------handleSuccess-------')
        console.log(response)
        this.$message.success('文件 [' + file.name + '] 上传成功')
      },
      // 文件上传失败
      handleError (err, file, fileList) {
        console.log('-------handleError-------')
        console.log(err)
        this.$message.error('文件上传失败')
      }

http-request 自定义上传实现,需要注意的是上传的文件需要封装在FormData里,并添加一个headers设置'multipart.form-data',

this.$http.post(url, data, config)  这里的$http就是axios

      // 覆盖默认的上传行为,可以自定义上传的实现
      httpRequest (param) {
        console.log(param)
        const fileObj = param.file // 获取file文件
        const formData = new FormData() // FormData对象
        formData.append('file', fileObj) // file封装到FormData里
        // 请求后台上传数据的接口
        this.$http.post('/upload', formData, {
          headers: { 'Content-Type': 'multipart/form-data' }
          // url: '/upload',
          // data: formData
          // method: 'post'
        }).then(res => {
          console.log('-------res--------')
          console.log(res)
          if (res.data.meta.status === '200') {
            this.$message.success(res.data.meta.msg)
            // 清空文件列表
            this.fileList = []
          } else {
            this.$message.error(res.data.meta.msg)
          }
        }, err => {
          console.log('-------err--------')
          console.log(err)
          this.$message.error('上传文件内容有问题,请保证上传文件字段均不为空且正确')
        })
      }

手动上传

    submitUpload () {
        if (this.fileList.length === 0) { // 上传文件列表为空
          this.$message.warning('请选择一个上传文件')
        } else { // 执行上传操作
          this.$refs.upload.submit()
        }
    }

【完整代码】

<template>
  <div> 
    <el-card>
      <!-- 下载数据模板 -->
      <div class="div-label"><label>上传文件之前请先下载<span style="font-weight: bold">数据模板</span></label></div>
      <el-button @click="download" class="el-button-color add-button-box" size="medium" type="primary">
        <i class="el-icon-download el-icon--right"></i>下载数据模板
      </el-button>
      <!-- 上传文件 -->
      <div class="div-label"><label>上传文件,仅支持<span style="font-weight: bold">.xlsx</span>格式的Excel文件,且大小不超过<span
        style="font-weight: bold;color: red">10MB</span></label></div>
      <el-upload
        class="upload-demo"
        ref="upload"
        action
        accept=".xlsx"
        :limit="1"
        :file-list="fileList"
        :auto-upload="false"
        :on-exceed="handleExceed"
        :on-preview="handlePreview"
        :on-change="handleChange"
        :on-remove="handleRemove"
        :before-upload="beforeUpload"
        :http-request="httpRequest"
        :on-success="handleSuccess"
        :on-error="handleError">
        <el-button slot="trigger" size="medium" type="primary">选取文件</el-button>
        <el-button style="margin-left: 10px;" size="medium" type="success" @click="submitUpload">上传到服务器</el-button>
      </el-upload>
    </el-card>
  </div>
</template>

<script>
  export default {
    name: 'Upload',
    data () {
      return {
        fileList: []
      }
    },
    methods: {
      // 下载本地文件
      download () {
        window.location.href = 'http://localhost:8080/template/template.xlsx'
      },
      // 超过文件上传最大个数
      handleExceed (files, fileList) {
        this.$message.warning('很抱歉当前支持最大上传文件个数为 1 个!')
      },
      // 文件上传到服务器之前的文件校验
      beforeUpload (file) {
        const extension = file.name.substring(file.name.lastIndexOf('.') + 1)
        const size = file.size / 1024 / 1024
        if (extension !== 'xlsx') { // 校验文件格式
          this.$message.warning('只支持上传后缀名为.xlsx的Excel文件')
        }
        if (size > 10) { // 校验文件大小
          this.$message.warning('文件大小不能超过10MB')
        }
      },
      // 文件状态改变
      handleChange (file, fileList) {
        if (file) {
          this.fileList = fileList.slice(-3)
        }
      },
      // 文件删除时
      handleRemove (file, fileList) {
        console.log(file, fileList)
        this.fileList = [] // 文件列表置空
      },
      // 点击文件列表中已上传的文件时的钩子
      handlePreview (file) {
        console.log(file)
      },
      // 文件上传成功
      handleSuccess (response, file, fileList) {
        console.log('-------handleSuccess-------')
        console.log(response)
        this.$message.success('文件 [' + file.name + '] 上传成功')
      },
      // 文件上传失败
      handleError (err, file, fileList) {
        console.log('-------handleError-------')
        console.log(err)
        this.$message.error('文件上传失败')
      },
      // 覆盖默认的上传行为,可以自定义上传的实现
      httpRequest (param) {
        console.log(param)
        const fileObj = param.file // 获取file文件
        const formData = new FormData() // FormData对象
        formData.append('file', fileObj) // file封装到FormData里
        // 请求后台上传数据的接口
        this.$http.post('/upload', formData, {
          headers: { 'Content-Type': 'multipart/form-data' }
          // url: '/upload',
          // data: formData
          // method: 'post'
        }).then(res => {
          console.log('-------res--------')
          console.log(res)
          if (res.data.meta.status === '200') {
            this.$message.success(res.data.meta.msg)
            // 清空文件列表
            this.fileList = []
          } else {
            this.$message.error(res.data.meta.msg)
          }
        }, err => {
          console.log('-------err--------')
          console.log(err)
          this.$message.error('上传文件内容有问题,请保证上传文件字段均不为空且正确')
        })
      },
      // 上传文件
      submitUpload () {
        if (this.fileList.length === 0) { // 上传文件列表为空
          this.$message.warning('请选择一个上传文件')
        } else { // 执行上传操作
          this.$refs.upload.submit()
        }
      }
    }
  }
</script>

<style scoped>
  .div-label {
    padding: 20px 0;
    width: 100%;
  }
</style>

参考:

https://www.jianshu.com/p/ea2b8ef30ffc

https://www.cnblogs.com/pinkpinkc/p/13221705.html

https://www.cnblogs.com/carriezhao/p/12707058.html

  • 14
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值