Vue实现多文件上传功能(前端 + 后端代码)
本人业余前端开发,因为公司(很坑)觉得我很牛逼,所以让我前后端一起玩,无奈的我只能磕磕碰碰的研究起了vue。
开发项目的时候,用到文件上传的功能很常见,包括单文件上传和多文件上传,上传各种类型的文件。在vue里面要实现多文件上传功能,还是很方便的。
本文就一起来学习一下,如何把多文件上传功能封装成一个组件,后面需要使用的时候,直接两三行代码就能搞定。
1、前端代码
首先我们先看前端,如何把它封装成一个组件。我们在调用它的时候,可能需要从外部传入一些参数给它,所以我们需要定义一些传入参数。这些参数我们可以放到props里面
export default {
props: {
// 值
value: [String, Object, Array],
// 大小限制(MB)
fileSize: {
type: Number,
default: 2,
},
// 文件类型, 例如['png', 'jpg', 'jpeg']
fileType: {
type: Array,
default: () => [".jpg", ".jpeg", ".png", ".doc", ".xls", ".xlsx", ".ppt", ".txt", ".pdf"],
},
// 是否显示提示
isShowTip: {
type: Boolean,
default: true
},
// 单据id
billId: {
type: Number,
require: true
},
// 单据类型
billType: {
type: Number,
required: true
}
}
}
上面定义了一些文件大小,文件类型等,如果没有传入,则为默认值。单据类型和单据id是必须要传入的,这里可以依照实际开发需要进行定义即可。
文件上传组件,我们可以使用element的el-upload
,在页面引入,我们点击后一般唤醒的是一个文件上传弹窗,可以使用el-dialog
标签包围。完整代码如下
<template>
<el-dialog title="附件上传" :visible.sync="visible" width="800px" :close-on-click-modal="false" @close="cancel">
<div class="upload-file">
<el-upload
:action="action"
:before-upload="handleBeforeUpload"
:file-list="fileList"
:limit="3"
multiple
:accept="accept"
:on-error="handleUploadError"
:on-exceed="handleExceed"
:on-success="handleUploadSuccess"
:on-change="handChange"
:http-request="httpRequest"
:show-file-list="true"
:auto-upload="false"
class="upload-file-uploader"
ref="upload"
>
<!-- 上传按钮 -->
<el-button slot="trigger" size="mini" type="primary">选取文件</el-button>
<el-button style="margin-left: 10px;" :disabled="fileList.length < 1" size="small" type="success" @click="submitUpload">上传到服务器</el-button>
<!-- 上传提示 -->
<div class="el-upload__tip" slot="tip" v-if="showTip">
请上传
<template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
<template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
的文件
</div>
</el-upload>
<!-- 文件列表 -->
<transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
<li :key="file.uid" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in list">
<el-link :href="file.url" :underline="false" target="_blank">
<span class="el-icon-document"> {{ getFileName(file.name) }} </span>
</el-link>
<div class="ele-upload-list__item-content-action">
<el-link :underline="false" @click="handleDelete(index)" type="danger">删除</el-link>
</div>
</li>
</transition-group>
</div>
</el-dialog>
</template>
上面用到的几个变量,我们需要在data里面定义
data() {
return {
// 已选择文件列表
fileList: [],
// 是否显示文件上传弹窗
visible: false,
// 可上传的文件类型
accept: '',
action: 'action'
};
},
accept
字段需要在页面创建后,通过传入或默认的fileType
字段进行拼接得到
created() {
this.fileList = this.list
// 拼接
this.fileType.forEach(el => {
this.accept += el
this.accept += ','
})
this.fileType.slice(0, this.fileList.length - 2)
},
接下来就是文件上传相关的方法,这里我们使用选择文件后手动上传的方式,请看下面的代码
<el-upload
:action="action" // 手动上传,这个参数没有用,但因为是必填的,所以随便填一个值就行
:before-upload="handleBeforeUpload" // 文件上传之前进行的操作
:file-list="fileList" // 已选择文件列表
:limit="3" // 一次最多上传几个文件
multiple // 可以多选
:accept="accept" // 可以上传的文件类型
:on-error="handleUploadError" // 上传出错时调用
:on-exceed="handleExceed" // 文件数量超过限制时调用
:on-success="handleUploadSuccess" // 上传成功时调用
:on-change="handChange" // 文件发生变化时调用
:http-request="httpRequest" // 自定义的文件上传方法,我们手动点击上传按钮后会调用
:show-file-list="true" // 是否显示文件列表
:auto-upload="false" // 关闭自动上传
class="upload-file-uploader"
ref="upload"
>
<!-- 上传按钮 -->
<el-button slot="trigger" size="mini" type="primary">选取文件</el-button>
<el-button style="margin-left: 10px;" :disabled="fileList.length < 1" size="small" type="success" @click="submitUpload">上传到服务器</el-button>
点击上传到服务器后,就触发submitUpload
调用我们自定义的方法。
注意这里选取文件的按钮需要加上slot="trigger"
属性,不然点击上传到服务器按钮后,也会触发选择文件弹框。
接下来看相关的方法
methods: {
// 外部调用这个方法,显示文件上传弹窗
show() {
this.visible = true
},
// 上传前校检格式和大小
handleBeforeUpload(file) {
// 校检文件类型
if (this.fileType) {
let fileExtension = "";
if (file.name.lastIndexOf(".") > -1) {
fileExtension = file.name.slice(file.name.lastIndexOf("."));
}
const isTypeOk = this.fileType.some((type) => {
if (file.type.indexOf(type) > -1) return true;
if (fileExtension && fileExtension.indexOf(type) > -1) return true;
return false;
});
if (!isTypeOk) {
this.$message.error(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`);
return false;
}
}
// 校检文件大小
if (this.fileSize) {
const isLt = file.size / 1024 / 1024 < this.fileSize;
if (!isLt) {
this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`);
return false;
}
}
return true;
},
// 文件个数超出
handleExceed() {
this.$message.error(`只允许上传3个文件`);
},
// 上传失败
handleUploadError(err) {
this.$message.error("上传失败, 请重试");
},
// 上传成功回调
handleUploadSuccess(res, file) {
this.$message.success("上传成功");
this.cancel()
},
/** 文件状态改变时调用 */
handChange(file, fileList) {
this.fileList = fileList
},
// 删除文件
handleDelete(index) {
this.fileList.splice(index, 1);
},
// 获取文件名称
getFileName(name) {
if (name.lastIndexOf("/") > -1) {
return name.slice(name.lastIndexOf("/") + 1).toLowerCase();
} else {
return "";
}
},
/** 手动提交上传 */
submitUpload() {
if (this.fileList.length <= 0) {
return false
}
this.$refs.upload.submit()
},
/** 关闭上传弹框 */
cancel() {
this.fileList = []
this.visible = false
},
/** 调用接口上传 */
httpRequest(param) {
const formData = new FormData()
formData.append("billId", this.billId)
formData.append("formType", this.billType)
formData.append('file', param.file)
uploadFormFile(formData).then(res => {
if(res.code === 200){
// 自定义上传时,需自己执行成功回调函数
param.onSuccess()
this.$refs.upload.clearFiles()
this.msgSuccess("上传成功")
// 回调方法,文件上传成功后,会调用`input`指定的方法,在调用方定义
this.$emit("input", res.data)
}
}).catch((err)=>{})
}
}
其他方法都还好,主要看看这个httpRequest
方法,如果直接使用url的方式进行调用,会出现跨域问题,你需要把token放到请求头里。我这里是通过封装后的api接口进行调用的,已经做了全局的token验证,所以只需要把相关的参数带上即可。
使用formData
带上需要的参数。上传成功后,使用this.$emit("input", res.data)
执行上传成功后的逻辑。
这就封装好了一个文件上传的组件,接下来看看怎么使用。
2、使用组件
在使用的页面,首先需要引入组件
import FileUpload from '@/components/FileUpload'
然后再页面内进行调用
<file-upload ref="fileUploadDialog" :billId="this.form.noticeId" :billType="10" @input="getAttachList"></file-upload>
billId
和billType
是我们动态传入的参数,其他的参数使用默认值,getAttachList
方法在文件上传成功后执行。
我们需要一个按钮唤醒文件上传框
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
:disabled="notEdit"
>上传</el-button>
定义hangAdd
方法,直接调用组件里定义的show
方法即可
handleAdd() {
this.$refs.fileUploadDialog.show()
},
然后定义文件上传成功后的方法,获取已上传文件列表即可。
getAttachList() {
this.loading = true
this.attachQuery.billId = this.form.noticeId
this.attachQuery.billType = 10
listAttachment(this.attachQuery).then(response => {
this.attachList = response.rows
this.attachList.forEach(el => {
// 转为kb,取小数点后2位
el.fileSize = parseFloat(el.fileSize / 1024).toFixed(2)
})
this.attachTotal = response.total
this.loading = false
}).catch(() => {})
},
到这里前端代码就大功告成了。
3、后端代码
我这里选择上传图片到阿里云服务器,上传到哪里不重要
/**
* 单据附件上传
* @param billId 单据id
* @param formType 单据类型
* @param file 上传的文件
* @return
* @throws Exception
*/
@PostMapping("/form/attachment/upload")
public AjaxResult uploadFormFile(@RequestParam(value = "billId") Long billId,
@RequestParam(value = "formType") Integer formType,
@RequestParam("file") MultipartFile[] file) throws Exception {
try {
// 文件上传后的路径
List<String> pathList = new ArrayList<>();
for (MultipartFile f : file) {
if (!f.isEmpty()) {
// 调用接口上传照片
AjaxResult result = uploadService.uploadFormFile(f, billId, formType);
if (!result.get("code").toString().equals("200")) {
return AjaxResult.error("上传文件异常,请联系管理员");
}
pathList.add(result.get("data").toString());
}
}
// 返回图片路径
return AjaxResult.success(pathList);
} catch (Exception e) {
return AjaxResult.error(e.getMessage());
}
}
这里我们使用一个MultipartFile
数组接受文件,然后调用方法判断文件的一些属性上传文件即可,具体的上传方法这里就不贴了,各有不同,具体情况具体分析。
到这里,本文就ok了。关于MIME 类型列表,可以点击这里查看。如果过程中遇到什么问题,可以在下方留言,我会回复的。
觉得好的可以帮忙点个赞啊,也可以关注我的公众号【秃头哥编程】
Vue实现多文件上传功能(前端 + 后端代码)的更多相关文章
- 使用element的upload组件实现一个完整的文件上传功能(上)
说到标题就有点心塞了,前段时间项目上需要实现一个文件上传的功能,然后就咔咔的去用了element的upload组件,不用不知道一用吓一跳哇. 在使用的过程中遇到了很多让意想不到的问题,后来也因为时间问 ...
- 使用element的upload组件实现一个完整的文件上传功能(下)
本篇文章是<使用element的upload组件实现一个完整的文件上传功能(上)>的续篇. 话不多说,接着上一篇直接开始 一.功能完善—保存表格中每一列的文件列表状态 1.思路 保存表格中 ...
- vue之element-ui文件上传
vue之element-ui文件上传 文件上传需求 对于文件上传,实际项目中我们的需求一般分两种: 对于单个的文件上传,比如拖动上传个图片之类的,或者是文件. 和表单一起实现上传(这种情况一般都是 ...
- 文件/大文件上传功能实现(JS+PHP)全过程
文件/大文件上传功能实现(JS+PHP) 参考博文:掘金-橙红年代 前端大文件上传 路漫漫 其修远 PHP + JS 实现大文件分割上传 本文是学习文件上传后的学习总结文章,从无到有实现文件上传功能, ...
- vue+axios+elementUI文件上传与下载
vue+axios+elementUI文件上传与下载 Simple_Learn 关注 0.5 2018.05.30 10:20 字数 209 阅读 15111评论 4喜欢 6 1.文件上传 这里主要 ...
- iOS 的 Safari 文件上传功能详解
iOS 6 给 Safari 浏览器带来的另外一个功能是文件上传,终于 Safari 终于支持 input 输入框的文件类型了,并且还支持 HTML媒体捕获(HTML Media Capture). ...
- [php基础]PHP.INI配置:文件上传功能配置教程
昨天分享了在PHP网站开发中如何在php.ini中配置实现session功能的PHP教程,今天继续分享在利用PHP实现文件上传功能时几点关键php.ini的配置. 说到在php.ini中的文件上传的配 ...
- 达到HTTP合约Get、Post和文件上传功能——采用WinHttp介面
于<采用WinHttp实现HTTP协议Get.Post和文件上传功能>一文中,我已经比較具体地解说了怎样使用WinHttp接口实现各种协议. 在近期的代码梳理中,我认为Post和文件上传模 ...
- 学习ASP.NET Core Razor 编程系列十五——文件上传功能(三)
学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...
随机推荐
- jenkins pipeline构建后返回构建结果给gitlab
jenkins pipeline构建后返回构建结果给gitlab 使用场景 gitlab 合并请求时要求管道任务必须成功,否则无法执行合并操作,又不想使用gitlab ci 工具. 实现方法 1.Ge ...
- Raspberry Pi:树莓派安装基础系统 Raspberry Pi(树莓派系统)
准备材料 树莓派4B 树莓派系统镜像 SDFormatter (格式化工具) Win32DiskImager (镜像拷录工具) 镜像下载 Rspberry Pi (2020-08-24版本比较稳定) ...
- [心得]zookeeper
1. 什么是zookeeper? 分布式协调服务 是一个典型的分布式数据一致性解决方案,分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/订阅.负载均衡.命名服务.分布式协调/通知.集群管 ...
- openjudge走迷宫(DFS)
题目: 描述 一个迷宫由R行C列格子组成,有的格子里有障碍物,不能走:有的格子是空地,可以走. 给定一个迷宫,求从左上角走到右下角最少需要走多少步(数据保证一定能走到).只能在水平方向或垂直方向走,不 ...
- Formily教程 | formily是中后台复杂场景的表单解决方案
前言 formily 不是一个简单的前端轮子.Formily 是一个由阿里巴巴集团多 BU 共建的面向中后台复杂场景的表单解决方案,它也是一个表单框架.它的前身是供应链平台在 2019 年初对外开源的 ...
- ROS2学习之旅(2)——配置ROS2环境
目录 1.source一下setup文件 2.自动source 3.自动进入工作区(不常用) 4.检查环境变量是否设置成功 5.总结 ROS2依赖于使用shell(终端)环境组合工作空间的概念.工作空 ...
- Python语言的技术领域
第一部分:各个领域应用的语言 大家看这个内容,其实你很明显发现,其实各个语言都有他的用处.我们可以说Python是应用最广的.但是暂时还是不能说它是全能的,因为他也有它的短板,但是对于一般的小公司和小 ...
- 秒懂 Java 的三种代理模式
前言 代理(Proxy)模式是一种结构型设计模式,提供了对目标对象另外的访问方式:即通过代理对象访问目标对象. 这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能. ...
- P5311 [Ynoi2011] 成都七中
P5311 [Ynoi2011] 成都七中 题意 给你一棵 \(n\) 个节点的树,每个节点有一种颜色,有 \(m\) 次查询操作. 查询操作给定参数 \(l\ r\ x\),需输出: 将树中编号在 ...
- Pelles C编译时出现的“POLINK: fatal error: 拒绝访问”问题的一种可能成因
在使用PellesC编译程序时,第一遍能正常编译执行,第二遍就无法编译,出现以下问题提示: Building NEWprogram2.exe. POLINK: fatal error: 拒绝访问. * ...