[Vue]写一个简单的文件上传控件

博客 动态
0 281
羽尘
羽尘 2022-04-20 15:58:13
悬赏:0 积分 收藏

[Vue]写一个简单的文件上传控件

?这篇将介绍如何写一个简单的基于Vue+Element的文件上传控件。

控件将具有

1. 上传队列的列表,显示文件名称,大小等信息,可以显示上传进度实时刷新

2. 取消上传

?

 使用Element的uploader控件,上传文件的行为和样式不用自己全部实现,使代码简化。且有足够的扩展性,文件传输请求的代码可以基于axios完全自己重写。我们只用关心核心代码。

搭建项目框架

首先建立一个空白的项目,引入Element控件库,具体的操作和使用Element控件库请看官方文档:

组件 | Element

后端项目框架的搭建,请阅读:[.Net 6]写一个简单的文件上传控件后端 - 林晓lx - 博客园 (cnblogs.com)

编写文件上传代码

编写文件上传的帮助类,新建ajaxRequire.ts并键入以下内容:

import axios, { CancelTokenSource } from 'axios'//发送网络请求export const request = async (url: string, methods, data: any, onProgress?: (e)=>void, cancelToken?: CancelTokenSource) => {       let token = null    let timeout = 3000;    if (cancelToken) {        token = cancelToken.token        timeout = 0;    }    const service = axios.create()    const re = await service.request({        headers: {'Content-Type': 'multipart/form-data'},        url: url,        method: methods,        data: data,        cancelToken: token,        timeout: timeout,        onUploadProgress: function (progressEvent) { //原生获取上传进度的事件            if (progressEvent.lengthComputable) {                if (onProgress) {                    onProgress(progressEvent);                }            }        },    })    return re as any;}///获得取消令牌export const getCancelToken = () => {    const source = axios.CancelToken.source();    return source;}

onUploadProgress回调函数将在数据传输进度变化的时候触发,携带progressEvent 原生获取上传进度事件参数,progressEvent.lengthComputable用于判断是否可以进行进度计算

axios.CancelToken.source()可以获得一个源,这个源包含一个唯一Id用于标识哪个请求,和一个cancel函数用于取消请求

编写控件

在App.vue中添加核心的控件 <el-upload>

接着添加属性,注意我们将用自己的方法upload替换el-upload中的上传操作,因此设置action="/",

:http-request="upload",如下:

<el-upload      ref="upload"      :limit="10"      multiple      action="/"      :http-request="upload"></el-upload>

在script中添加上传Dto:一些业务相关的数据在这里定义 比如ownerUserId, fileContainerName等,这些数据可以通过表单与文件数据一并上传

export class CreateFileDto {  id: string;  fileContainerName: string; //文件夹名称  parentId: string;          //文件的父Id  ownerUserId: number;        //文件的归属用户Id  fileName: string;  mimeType: string;  fileType: number; //文件类型 0:文件夹,1:普通文件  file: any;        //文件数据}

method中添加一些帮助类函数:

methods: {  successMessage(value = "执行成功") {      this.$notify({        title: "成功",        message: value,        type: "success",      });    },  errorMessage(value = "执行错误") {      this.$notify.error({        title: "错误",        message: value,      });    },  FriendlyFileSize(bytes) {      bytes = parseFloat(bytes);      if (bytes === 0) return "0B";      let k = 1024,        sizes = ["B", "KB", "MB", "GB", "TB"],        i = Math.floor(Math.log(bytes) / Math.log(k));      return (bytes / Math.pow(k, i)).toPrecision(3) + sizes[i];    },}

编写提交前置函数,这里将做验证和生成cancelToken:

beforeUpload(file) {      var token = getCancelToken();      file.cancelToken = token;      let isLt2M = true;      if (this.fileSizeLimit < 0) {        return true;      }      isLt2M = file.size / 1024 / 1024 < this.fileSizeLimit;      if (!isLt2M) {        this.loading = false;        this.errorMessage(`"上传文件大小不能超过 ${this.fileSizeLimit}}MB!"`);      }      return isLt2M;}

 编写upload函数,用于组装请求数据并交给 ajaxRequire 执行上传任务

  async upload(option) {      this.loaded = true;      var model = new CreateFileDto();      var file = option.file;      model.fileName = file.name;      model.fileType = 2;      model.mimeType = file.type;      model.ownerUserId = 1;      model.fileContainerName = "Container1";      model.file = file;      var fd = new FormData();      Enumerable.from(model).forEach((c) => {        fd.append(c.key, c.value);      });      var token = file.cancelToken;      await request(        this.uploadUrl,        "post",        fd,        (e) => {          if (e.total > 0) {            e.percent = (e.loaded / e.total) * 100;          }          option.onProgress(e);        },        token      );    },

将token将作为取消传输的入口交给ajaxRequire ,自己也保留这个对象用于发送取消命令,相当于“一式两份”。

添加el-upload各阶段函数的订阅

:before-upload="beforeUpload"
:on-success="handleSuccess"
:on-remove="handleRemove"
:on-error="handleError"

    handleSuccess(response, file, fileList) {      this.successMessage("上传成功");      this.loading = false;    },    handleError(e, file, fileList) {      this.errorMessage(e);      this.loading = false;    },    handleRemove(file, fileList) {      if (file.raw.cancelToken) {        file.raw.cancelToken.cancel();      }    },

编写上传队列的Html代码:

      <el-button ref="uploadButton">上传</el-button>      <span slot="file" slot-scope="{ file }">        <div class="filelist-item">          <el-row>            <el-col :span="6" class="file-icon-frame">              <i class="el-icon-document file-icon"></i>            </el-col>            <el-col :span="18">              <el-row>                <el-col :span="20">                  <label class="file-title">                    {{ file.name }}                  </label>                </el-col>                <el-col :span="4" style="text-align: right">                  <el-button                    type="danger"                    icon="el-icon-minus"                    size="mini"                    circle                    @click="handleRemove(file)"                  ></el-button>                </el-col>                <el-col :span="24">                  <label class="file-size">                    {{ FriendlyFileSize(file.size) }}                  </label>                </el-col>                <el-col :span="24">                  <el-progress                    :text-inside="true"                    :stroke-width="26"                    :percentage="parseInt(file.percentage, 10)"                    :status="                      parseInt(file.percentage, 10) == 100 ? 'success' : ''                    "                  >                  </el-progress                ></el-col>              </el-row>            </el-col>          </el-row>        </div>      </span>

运行

进入后端项目的目录(api),运行:

dotnet run

前端项目目录(web),运行

yarn serve

运行效果:

 

 ?

 

 

完整代码:

file-uploader-sample/web at master · jevonsflash/file-uploader-sample (github.com)

项目地址:

jevonsflash/file-uploader-sample (github.com)

?
posted @ 2022-04-20 15:10 林晓lx 阅读(43) 评论(0) 编辑 收藏 举报
回帖
    羽尘

    羽尘 (王者 段位)

    2335 积分 (2)粉丝 (11)源码

     

    温馨提示

    亦奇源码

    最新会员