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

vue

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

控件将具有

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

2. 取消上传

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

搭建项目框架

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

组件 | Element

后端项目框架的搭建,请阅读:

编写文件上传代码

编写文件上传的帮助类,新建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)

以上是 [Vue]写一个简单的文件上传控件 的全部内容, 来源链接: utcz.com/z/381033.html

回到顶部