本人业余前端开发,因为公司(很坑)觉得我很牛逼,所以让我前后端一起玩,无奈的我只能磕磕碰碰的研究起了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>

billIdbillType是我们动态传入的参数,其他的参数使用默认值,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实现多文件上传功能(前端 + 后端代码)的更多相关文章

  1. 使用element的upload组件实现一个完整的文件上传功能(上)

    说到标题就有点心塞了,前段时间项目上需要实现一个文件上传的功能,然后就咔咔的去用了element的upload组件,不用不知道一用吓一跳哇. 在使用的过程中遇到了很多让意想不到的问题,后来也因为时间问 ...

  2. 使用element的upload组件实现一个完整的文件上传功能(下)

    本篇文章是<使用element的upload组件实现一个完整的文件上传功能(上)>的续篇. 话不多说,接着上一篇直接开始 一.功能完善—保存表格中每一列的文件列表状态 1.思路 保存表格中 ...

  3. vue之element-ui文件上传

    vue之element-ui文件上传 文件上传需求 ​ 对于文件上传,实际项目中我们的需求一般分两种: 对于单个的文件上传,比如拖动上传个图片之类的,或者是文件. 和表单一起实现上传(这种情况一般都是 ...

  4. 文件/大文件上传功能实现(JS+PHP)全过程

    文件/大文件上传功能实现(JS+PHP) 参考博文:掘金-橙红年代 前端大文件上传 路漫漫 其修远 PHP + JS 实现大文件分割上传 本文是学习文件上传后的学习总结文章,从无到有实现文件上传功能, ...

  5. vue+axios+elementUI文件上传与下载

    vue+axios+elementUI文件上传与下载 Simple_Learn 关注  0.5 2018.05.30 10:20 字数 209 阅读 15111评论 4喜欢 6 1.文件上传 这里主要 ...

  6. iOS 的 Safari 文件上传功能详解

    iOS 6 给 Safari 浏览器带来的另外一个功能是文件上传,终于 Safari 终于支持 input 输入框的文件类型了,并且还支持 HTML媒体捕获(HTML Media Capture). ...

  7. [php基础]PHP.INI配置:文件上传功能配置教程

    昨天分享了在PHP网站开发中如何在php.ini中配置实现session功能的PHP教程,今天继续分享在利用PHP实现文件上传功能时几点关键php.ini的配置. 说到在php.ini中的文件上传的配 ...

  8. 达到HTTP合约Get、Post和文件上传功能——采用WinHttp介面

    于<采用WinHttp实现HTTP协议Get.Post和文件上传功能>一文中,我已经比較具体地解说了怎样使用WinHttp接口实现各种协议. 在近期的代码梳理中,我认为Post和文件上传模 ...

  9. 学习ASP.NET Core Razor 编程系列十五——文件上传功能(三)

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

随机推荐

  1. jenkins pipeline构建后返回构建结果给gitlab

    jenkins pipeline构建后返回构建结果给gitlab 使用场景 gitlab 合并请求时要求管道任务必须成功,否则无法执行合并操作,又不想使用gitlab ci 工具. 实现方法 1.Ge ...

  2. Raspberry Pi:树莓派安装基础系统 Raspberry Pi(树莓派系统)

    准备材料 树莓派4B 树莓派系统镜像 SDFormatter (格式化工具) Win32DiskImager (镜像拷录工具) 镜像下载 Rspberry Pi (2020-08-24版本比较稳定) ...

  3. [心得]zookeeper

    1. 什么是zookeeper? 分布式协调服务 是一个典型的分布式数据一致性解决方案,分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/订阅.负载均衡.命名服务.分布式协调/通知.集群管 ...

  4. openjudge走迷宫(DFS)

    题目: 描述 一个迷宫由R行C列格子组成,有的格子里有障碍物,不能走:有的格子是空地,可以走. 给定一个迷宫,求从左上角走到右下角最少需要走多少步(数据保证一定能走到).只能在水平方向或垂直方向走,不 ...

  5. Formily教程 | formily是中后台复杂场景的表单解决方案

    前言 formily 不是一个简单的前端轮子.Formily 是一个由阿里巴巴集团多 BU 共建的面向中后台复杂场景的表单解决方案,它也是一个表单框架.它的前身是供应链平台在 2019 年初对外开源的 ...

  6. ROS2学习之旅(2)——配置ROS2环境

    目录 1.source一下setup文件 2.自动source 3.自动进入工作区(不常用) 4.检查环境变量是否设置成功 5.总结 ROS2依赖于使用shell(终端)环境组合工作空间的概念.工作空 ...

  7. Python语言的技术领域

    第一部分:各个领域应用的语言 大家看这个内容,其实你很明显发现,其实各个语言都有他的用处.我们可以说Python是应用最广的.但是暂时还是不能说它是全能的,因为他也有它的短板,但是对于一般的小公司和小 ...

  8. 秒懂 Java 的三种代理模式

    前言 代理(Proxy)模式是一种结构型设计模式,提供了对目标对象另外的访问方式:即通过代理对象访问目标对象. 这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能. ...

  9. P5311 [Ynoi2011] 成都七中

    P5311 [Ynoi2011] 成都七中 题意 给你一棵 \(n\) 个节点的树,每个节点有一种颜色,有 \(m\) 次查询操作. 查询操作给定参数 \(l\ r\ x\),需输出: 将树中编号在 ...

  10. Pelles C编译时出现的“POLINK: fatal error: 拒绝访问”问题的一种可能成因

    在使用PellesC编译程序时,第一遍能正常编译执行,第二遍就无法编译,出现以下问题提示: Building NEWprogram2.exe. POLINK: fatal error: 拒绝访问. * ...