如何通过vue和Element-plus实现文件上传和下载的进度显示

1. 简介

文件上传和下载是Web开发中常见的功能要求之一。在Vue框架中,使用Element-plus插件可以方便地实现文件上传和下载的功能。本文将介绍如何使用Vue和Element-plus实现文件上传和下载,并在上传和下载过程中展示进度。

2. 文件上传

2.1 安装Element-plus

首先,我们需要安装Element-plus插件。在终端中运行以下代码:

npm i element-plus -S

安装完成后,在main.js中引入该插件:

import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/lib/theme-chalk/index.css'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(ElementPlus)
app.use(router)

app.mount('#app')

2.2 模板代码

接下来,我们需要编写文件上传的模板代码。

<template>
  <el-upload
    class="upload-demo"
    :action="uploadUrl"
    :on-preview="handlePreview"
    :on-remove="handleRemove"
    :before-upload="beforeUpload"
    :on-success="handleSuccess"
    :on-error="handleError"
    :file-list="fileList"
    multiple>
    <el-button slot="trigger" size="small" type="primary">选取文件</el-button>
    <template slot="tip">只能上传jpg/png文件,且不超过500kb</template>
  </el-upload>
</template>
<script>
import { ref } from 'vue'
export default {
  name: 'uploadDemo',
  setup() {
    const fileList = ref([])
    const uploadUrl = 'https://jsonplaceholder.typicode.com/posts/'
    const beforeUpload = (file) => {
      if (file.type !== 'image/png' && file.type !== 'image/jpeg') {
        alert('只能上传jpg/png文件哦!')
        return false
      }
      if (file.size > 500 * 1024) {
        alert('文件大小不能超过 500KB!')
        return false
      }
      return true
    }
    const handleSuccess = (response, file, fileList) => {
      console.log(response, file, fileList)
      alert('上传成功')
    }
    const handleError = (err, file, fileList) => {
      console.log(err, file, fileList)
      alert('上传失败')
    }
    const handlePreview = (file) => {
      console.log(file)
    }
    const handleRemove = (file, fileList) => {
      console.log(file, fileList)
    }
    return {
      fileList,
      uploadUrl,
      beforeUpload,
      handleSuccess,
      handleError,
      handlePreview,
      handleRemove
    }
  }
}

</script>

这里使用了Vue3中的Composition API来编写组件。在setup函数中定义了一些变量和函数,用于控制文件上传的行为。

2.3 代码解析

接下来,我们分别对上传组件中的代码进行解析和说明。

2.3.1 el-upload组件

上传组件是通过Element-plus中的el-upload组件实现的:

<el-upload
  class="upload-demo"
  :action="uploadUrl"
  :on-preview="handlePreview"
  :on-remove="handleRemove"
  :before-upload="beforeUpload"
  :on-success="handleSuccess"
  :on-error="handleError"
  :file-list="fileList"
  multiple>
  <el-button slot="trigger" size="small" type="primary">选取文件</el-button>
  <template slot="tip">只能上传jpg/png文件,且不超过500kb</template>

</el-upload>

这里我们使用了el-upload组件来实现文件上传功能。这个组件包含了一些属性和事件,用于控制上传行为。下面我们简单说明一下这些属性和事件的含义:

class: 为组件添加CSS类名

action: 上传的地址,可以是一个API接口

before-upload: 文件上传前的检查函数,可以在此处检查文件类型和大小等信息

on-success: Upload组件上传成功后调用的方法

on-error: Upload组件上传失败后调用的方法

fileList: 已上传的文件列表

在组件模板中,我们还定义了一个el-button组件,用于触发上传操作。

2.3.2 属性和事件

接下来我们来详细解析一下组件中定义的属性和事件:

:before-upload

:before-upload属性是一个上传前的检查函数,用于检查文件的类型和大小等信息。如果检查失败,可以返回一个 false 来中止上传。

const beforeUpload = (file) => {
  if (file.type !== 'image/png' && file.type !== 'image/jpeg') {
    alert('只能上传jpg/png文件哦!')
    return false
  }
  if (file.size > 500 * 1024) {
    alert('文件大小不能超过 500KB!')
    return false
  }
  return true

}

当文件类型不是png或者jpeg时,我们会弹出提示框,中止上传。同样,当文件大小超过500KB时,也会中止上传。

:on-success

:on-success 事件会在文件上传成功后触发,同时返回上传成功的信息。在这里,我们只是给用户一个提示框,告诉他文件上传成功了:

const handleSuccess = (response, file, fileList) => {
  console.log(response, file, fileList)
  alert('上传成功')

}

:on-error

:on-error 事件会在文件上传失败后触发,同时返回上传失败的信息。在这里,我们只是给用户一个提示框,告诉他文件上传失败了:

const handleError = (err, file, fileList) => {
  console.log(err, file, fileList)
  alert('上传失败')

}

:file-list

:file-list 属性是已上传的文件列表。在上面的组件中,我们使用 ref 来定义了一个 fileList 变量。

import { ref } from 'vue'
export default {
  name: 'uploadDemo',
  setup() {
    const fileList = ref([])
    // ...
    return { fileList /* ... */ }
  }

}

我们可以通过 ref 来定义一个变量,并在其他地方引用它。这里,我们将 fileList 变量作为一个属性,传递给el-upload组件,就可以把已上传的文件列表显示在界面上。

3. 文件下载

3.1 下载文件

接下来,我们来实现文件下载的功能。在Vue中,可以通过定义一个a标签来触发文件下载。我们可以通过在a标签的href属性中指定文件下载的地址,然后调用js代码的click方法来下载文件。

<template>
  <div>
    <a :href="downloadUrl" @click="downloadFile">下载文件</a>
  </div>
</template>
<script>
export default {
  name: 'downloadDemo',
  data() {
    return {
      downloadUrl: 'https://jsonplaceholder.typicode.com/posts/1'
    }
  },
  methods: {
    downloadFile() {
      window.open(this.downloadUrl, '_blank')
    }
  }
}

</script>

注意,这里的下载文件并不会显示进度条,这只是一个简单的下载示例。

3.2 显示进度条

为了在文件上传和下载的过程中展示进度条,我们需要使用axios库。axios是一个流行的HTTP库,可以在浏览器中发出AJAX请求,并支持PromiseAPI。

3.3 安装axios

首先,我们需要安装axios库。在终端中运行以下代码:

npm i axios -S

安装完成后,在main.js中引入该库,并将其绑定到Vue的原型链中:

import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/lib/theme-chalk/index.css'
import App from './App.vue'
import router from './router'
import axios from 'axios'
const app = createApp(App)
app.use(ElementPlus)
app.use(router)
app.config.globalProperties.$axios = axios

app.mount('#app')

现在我们已经可以在Vue组件中使用axios了。

3.4 文件下载进度

下面我们要实现的是文件下载时的进度条显示。

<template>
  <div>
    <el-button type="primary" @click="downloadFile">下载文件</el-button>
    <el-progress :percentage="progressPercentage" :status="progressStatus">{{progressText}}</el-progress>
  </div>
</template>
<script>
export default {
  name: 'downloadProgressDemo',
  data() {
    return {
      downloadUrl: 'https://jsonplaceholder.typicode.com/posts/1',
      progressStatus: 'info',
      progressPercentage: 0,
      progressText: ''
    }
  },
  methods: {
    downloadFile() {
      const url = this.downloadUrl
      const downloadElement = document.createElement('a')
      document.body.appendChild(downloadElement)
      downloadElement.setAttribute('href', url)
      downloadElement.setAttribute('download', '')
      downloadElement.setAttribute('target', '_blank')
      downloadElement.click()
      const config = {
        onDownloadProgress: (progressEvent) => {
          this.progressStatus = 'success'
          this.progressPercentage = Math.round((progressEvent.loaded / progressEvent.total) * 100)
          this.progressText = `${this.progressPercentage}% 下载完成`
        }
      }
      this.$axios({
        method: 'get',
        url: url,
        responseType: 'arraybuffer',
        ...config
      })
        .then(response => {
          console.log(response)
        })
        .catch(error => {
          console.log(error)
        })
    }
  }
}

</script>

这里定义了一个名为downloadProgressDemo的Vue组件,用于展示文件下载进度。在这个组件中,我们定义了一些变量和方法,用于控制进度条的显示。

在模板中,我们定义了一个按钮,用于触发文件下载功能,并在下面添加了一个进度条,用于展示下载的进度。

3.5 代码解析

3.5.1 点击下载按钮

下载文件的按钮对应以下代码:

<el-button type="primary" @click="downloadFile">下载文件</el-button>

点击下载按钮后,会调用 downloadFile 方法。

3.5.2 下载文件方法

在 downloadFile 方法中,我们通过创建一个a标签,将下载链接放在href属性中,然后通过调用click方法来下载文件。同时,在 axios 中设置了 onDownloadProgress 回调方法,用于每次下载时调用以更新进度条。

methods: {
  downloadFile() {
    const url = this.downloadUrl
    const downloadElement = document.createElement('a')
    document.body.appendChild(downloadElement)
    downloadElement.setAttribute('href', url)
    downloadElement.setAttribute('download', '')
    downloadElement.setAttribute('target', '_blank')
    downloadElement.click()
    const config = {
      onDownloadProgress: (progressEvent) => {
        this.progressStatus = 'success'
        this.progressPercentage = Math.round((progressEvent.loaded / progressEvent.total) * 100)
        this.progressText = `${this.progressPercentage}% 下载完成`
      }
    }
    this.$axios({
      method: 'get',
      url: url,
      responseType: 'arraybuffer',
      ...config
    })
      .then(response => {
        console.log(response)
      })
      .catch(error => {
        console.log(error)
      })
  }

}

其中 config 是一个axios请求的配置,它定义了一个 onDownloadProgress 方法,在每次下载时被调用以更新进度条。在这个方法中,我们通过计算已下载的数据量与总数据量的比例来计算进度百分比。然后将进度百分比更新到 progressPercentage 变量中,并将进度文本更新到 progressText 变量中。最后,我们将 progressStatus 设置为 'success',将进度条设置为绿色。

3.5.3 显示进度条

在模板代码中,我们使用 Element-plus 中的 el-progress 组件来展示进度条:

<el-progress :percentage="progressPercentage" :status="progressStatus">{{progressText}}</el-progress>

这里我们绑定了 :percentage 属性和 :status 属性,用于显示进度百分比和状态。同时,将进度文本作为插槽内容显示。

4. 总结

在本文中,我们介绍了如何使用Vue和Element-plus来实现文件上传和下载的功能,并在文件上传和下载的过程中展示进度条。借助于Element-plus和axios,我们可以很方便地实现这些功能,并且可以自定义进度条的样式和文本。希望本文对你有所帮助。