[Vue]写一个简单的文件上传控件
这篇将介绍如何写一个简单的基于Vue+Element的文件上传控件。
控件将具有
1. 上传队列的列表,显示文件名称,大小等信息,可以显示上传进度实时刷新
2. 取消上传
使用Element的uploader控件,上传文件的行为和样式不用自己全部实现,使代码简化。且有足够的扩展性,文件传输请求的代码可以基于axios完全自己重写。我们只用关心核心代码。
搭建项目框架
首先建立一个空白的项目,引入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]写一个简单的文件上传控件的更多相关文章
- 用python写一个简单的文件上传
用Pycharm创建一个django项目.目录如下: <!DOCTYPE html> <html lang="en"> <head> <m ...
- Java实现一个简单的文件上传案例
Java实现一个简单的文件上传案例 实现流程: 1.客户端从硬盘读取文件数据到程序中 2.客户端输出流,写出文件到服务端 3.服务端输出流,读取文件数据到服务端中 4.输出流,写出文件数据到服务器硬盘 ...
- jquery文件上传控件 Uploadify
(转自 http://www.cnblogs.com/mofish/archive/2012/11/30/2796698.html) 基于jquery的文件上传控件,支持ajax无刷新上传,多个文件同 ...
- 使用Uploadify(UploadiFive)多文件上传控件遇到的坑
最近项目中需要实现多文件上传功能,于是结合需求最终选择了Uploadify这一款控件来实现.相比其他控件,Uploadify具有简洁的界面,功能API基本可以解决大多数需求,又是基于jquery的,配 ...
- 在WebBrowser中通过模拟键盘鼠标操控网页中的文件上传控件(转)
引言 这两天沉迷了Google SketchUp,刚刚玩够,一时兴起,研究了一下WebBrowser. 我在<WebBrowser控件使用技巧分享>一文中曾谈到过“我现在可以通过WebBr ...
- jquery文件上传控件 Uploadify 可以和ajax交互
http://www.cnblogs.com/mofish/archive/2012/11/30/2796698.html 原网址 基于jquery的文件上传控件,支持ajax无刷新上传,多个文件同 ...
- jquery文件上传控件 Uploadify(转)
原文:http://www.cnblogs.com/mofish/archive/2012/11/30/2796698.html 基于jquery的文件上传控件,支持ajax无刷新上传,多个文件同时上 ...
- 因用了NeatUpload大文件上传控件而导致Nonfile portion > 4194304 bytes错误的解决方法
今天遇到一个问题,就是“NeatUpload大文件上传控件而导致Nonfile portion > 4194304 bytes错误”,百度后发现了一个解决方法,跟大家分享下: NeatUploa ...
- 对FileUpload文件上传控件的一些使用方法说明
//创建时间:2014-03-12 //创建人:幽林孤狼 //说明:FileUpload文件上传控件使用说明(只是部分)已共享学习为主 //可以上传图片,txt文档.doc,wps,还有音频文件,视屏 ...
随机推荐
- 类型转换Java day8
类型转换自动类型转换 从同种类型的低字节类型值直接转换到高类型字节值的转换可自动转换 类型自动转换示例 byte a = 20; int b = a;//不报错可正常转换 有些类型它在计算时默认以指定 ...
- 使用VS Code编译Marlin固件
参考:https://marlinfw.org/docs/basics/install_platformio_vscode.html 前言 在阅读本文之前,您应该已经阅读了使用 PlatformIO ...
- 关于.NET 6.0 Crossgen2的一些研究
NET 6.0引入了Crossgen工具的后续版本Crossgen2,这个工具提供了程序提前(AOT)编译的能力. 什么是CrossGen? 我们日常开发时使用C#编译器CSC编译一个.NET程序集, ...
- centos配置ssh服务并简单测试
最近在做计算机集群方面的东西,简单弄了一下ssh服务. 首先把前提情况介绍一下: 1.我是用的虚拟机先模拟的,也不是没有真机,就是跑来跑去麻烦. 2.装了三个相同配置的centos虚拟机,详细参数就不 ...
- 『现学现忘』Docker基础 — 35、实战:自定义CentOS镜像
目录 1.前提说明 2.编写Dockerfile文件 3.构建镜像 4.运行镜像 5.列出镜像的变更历史 1)目标:自定义镜像wokong_centos. 2)所用到的保留字指令: FROM:基础镜像 ...
- SpringMVC 和SpringBoot中的注解是如何起作用的,如何实现的
SpringMVC源码解读 - HandlerMapping - RequestMappingHandlerMapping初始化 https://www.cnblogs.com/leftthen/ ...
- JVM内存模型——堆(heap)、栈(stack)和方法区(method)
JAVA的JVM的内存可分为3个区:堆(heap).栈(stack)和方法区(method) 堆区:堆内存用于存放由new创建的对象和数组.堆是JVM管理的内存中最大的一块,堆被所有线程共享,目的 ...
- Xml 映射文件中,除了常见的 select|insert|updae|delete 标签之外,还有哪些标签?
<resultMap>.<parameterMap>.<sql>.<include>. <selectKey>,加上动态 sql 的 9 个 ...
- 在 Java 中,如何跳出当前的多重嵌套循环?
在最外层循环前加一个标记如 A,然后用 break A;可以跳出多重循环.(Java 中 支持带标签的 break 和 continue 语句,作用有点类似于 C 和 C++中的 goto 语 句,但 ...
- 接口是否可继承(extends)接口?抽象类是否可实现 (implements)接口?抽象类是否可继承具体类(concrete class)?
接口可以继承接口,而且支持多重继承.抽象类可以实现(implements)接口,抽象类可继承具体类也可以继承抽象类.