开发项目的时候,用到文件上传的功能很常见,包括单文件上传和多文件上传,上传各种类型的文件。在vue里面要实现多文件上传功能,还是很方便的。
本文就一起来学习一下,如何把多文件上传功能封装成一个组件,后面需要使用的时候,直接两三行代码就能搞定。
首先我们先看前端,如何把它封装成一个组件。我们在调用它的时候,可能需要从外部传入一些参数给它,所以我们需要定义一些传入参数。这些参数我们可以放到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>
<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"
ref="upload"
>
<!-- 上传按钮 -->
<el-button slot="trigger" size="mini" type="primary">选取文件</el-button>
<el-button :disabled="fileList.length < 1" size="small" type="success" @click="submitUpload">上传到服务器</el-button>
<!-- 上传提示 -->
<div slot="tip" v-if="showTip">
请上传
<template v-if="fileSize"> 大小不超过 <b>{{ fileSize }}MB</b> </template>
<template v-if="fileType"> 格式为 <b>{{ fileType.join("/") }}</b> </template>
的文件
</div>
</el-upload>
<!-- 文件列表 -->
<transition-group name="el-fade-in-linear" tag="ul">
<li :key="file.uid" v-for="(file, index) in list">
<el-link :href="file.url" :underline="false" target="_blank">
<span> {{ getFileName(file.name) }} </span>
</el-link>
<div>
<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" // 关闭自动上传
ref="upload"
>
<!-- 上传按钮 -->
<el-button slot="trigger" size="mini" type="primary">选取文件</el-button>
<el-button :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) 执行上传成功后的逻辑。
这就封装好了一个文件上传的组件,接下来看看怎么使用。
在使用的页面,首先需要引入组件
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(() => {})
},
到这里前端代码就大功告成了。
我这里选择上传图片到阿里云服务器,上传到哪里不重要
/**
* 单据附件上传
* @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 数组接受文件,然后调用方法判断文件的一些属性上传文件即可,具体的上传方法这里就不贴了,各有不同,具体情况具体分析。
原文 http://www.cnblogs.com/codetiger/p/15140457.html
h5里提供了webkitdirectory 来实现上传文件夹的功能,但它仅支持Chrome。上传文件–限制类型 添加accept属性,使用*会导致谷歌浏览器响应延迟,对IE和火狐没有影响 。如需规定多个值,请使用逗号分隔。
平时开发时可能会遇到上传图片问题,但如果是上传图片,多数是先进行上传然后才能回显,今天给大家介绍一个简单的上传前先对图片进行回显的方式,仅用一小部分js代码即可实现
上传文件的类型;具体做法如下所示:注意:accept属性可以限制上传格式,其有兼容性如下
下行速率一般是从网络上的主机获取数据的速率,各种网络软件的运用,都必须从网路上获取数据。上传速率(度)是指单位时间内,网络数据的上行流量。
谷歌浏览器升级到chrome52.0.2743.80版本以上,会出现点击上传文件选择框会延迟几秒才会显示 反应很慢的情况。方案一:修改accept参数;方案二:浏览器修改设置
在使用file上传文件的时候,想到了图片预览的功能,然后查询了一些资料,一种是需要后端配合,将数据变成base64或者buff等数据传给后端然后调取接口进行显示,但是这种需要后端的配合和网络请求,感觉不如在纯前端操作方便的多
在做上传文件的时候,大家会引入input标签。但在实现的过程中,在上传一个文件后,第二次上传同一个文件时会无法触发上传的代码,问题其实这样解决。
通过设置nginx的client_max_body_size解决nginx+php上传大文件的问题: 用nginx来做webserver的时,上传大文件时需要特别注意client_max_body_size这个参数,否则会中断在nginx的请求中,在php中是无法记录到访问的.
将图片发给后端 ajax:1.前端获取图片信息 文件域;2.将文件信息 存到formdata;3.调用后端写的api接口发送数据;b.接受返回的数据;前端页面显示图片
最近项目开发中涉及到文件上传功能,使用的是七牛的服务。查看七牛文档发现文件上传格式为blob,而本地添加上传文件时获取到的是file格式,因此需要将file转换为blob,具体转换方法如下:
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!