将文件上传的方法封装一下,供大家统一调用,
话不多说,直接上代码
- action 上传的地址
- accept 接受上传的文件类型
- multiple 是否开启多文件上传模式
- limit 限制上传个数
- fileList 文件列表
- disabled 是否禁用
- before-upload 上传文件之前的钩子.
- on-success 上传成功的钩子函数
- on-error 文件上传失败时的钩子
- on-exceed 文件超出个数限制时的钩子
- on-remove 文件列表移除文件时的钩子
- on-preview 点击文件列表中已上传的文件时的钩子.
- on-progress 文件上传时的钩子 进度条展示的基础
子组件
<slot name="uploadBtn">slot>
调用上传组件的父组件
<uploadBtn>
<template v-slot="uploadBtn">
<img src='http://test/upload.img'>img>
template>
uploadBtn>
说明
使用了具名插槽 将上传的按钮放在父组件调用子组件标签的容器中,这样的好处是:随意定制按钮不需要写一堆的条件判断,且可定制上传按钮
data定义office基础路径
officeOnlineAddress:'https://view.officeapps.live.com/op/view.aspx?src=',
office基础路径拼接文件路径并预览
const preveiewURL = this.officeOnlineAddress + target
window.open(preveiewURL)
说明
office基础路径拼接文件路径并用window.open即可实现文件的预览
代码
beforeUpload(file) {
const { name = '', size } = file
if (size > this.maxSize * 1024 * 1000) {
this.$Message.warning(`文件最大仅支持${this.maxSize}M`)
return false
}
if (!this.acceptTypeList.includes(name.split('.').pop())) {
this.$Message.warning(
`文件格式仅支持${this.acceptTypeList.join(',')}`
)
return false
}
},
说明
- 文件大小大于父组件传入的maxSize则拦截并提示
- 文件格式不正确则拦截并提示
- beforeUpload函数体中,如果函数的返回值是false,则终止上传
代码
preview (data) {
const { url, response = {} } = data || {}
let name = data.name
const downLoadTypeList = this.downLoadTypeList
const preveiwTypeList = this.preveiwTypeList
if (!name) {
name = ''
}
const suffixFileType = name.split('.').pop()
if (downLoadTypeList.includes(suffixFileType)) {
//下载 'doc', 'docx', 'xlsx', 'xls', 'txt' 文件
name = name.replace(/&/g, '') // & 不兼容
const target = encodeURIComponent(
Base64.encode(
`${
location.origin
}/api/abk/web/v1/resource/file?fileId=${
url || response.data
}&fullfilename=${name}&sid=4AC67ADB4E264AB0A8B899A671072875`
)
)
if (
this.officePreviewFlag &&
this.officeType.includes(suffixFileType)
) {
// office预览的
const preveiewURL = this.officeOnlineAddress + target
window.open(preveiewURL)
} else {
// 非office预览
window.open(
`https://test/preview/onlinePreview?url=${target}`,
'_blank'
)
}
} else if (preveiwTypeList.includes(suffixFileType)) {
//新窗口打开 预览图片文件
window.open(
'/api/abk/web/v1/resource/file?fileId=' +
(url || response.data),
'_blank'
)
}
},
说明
- 使用 name.split(‘.’).pop() 拿到文件的后缀名
- 根据传入的 downLoadTypeList(需要下载的文件类型)、preveiwTypeList(可以直接预览的文件类型)、officePreviewFlag(office文件类型)以及officePreviewFlag(是否启用office预览)和文件后缀名匹配
- 需要下载的文件类型 根据后端的下载基础路径拼接得到下载地址,并结合windwo.open下载
- 可以直接预览的文件类型 根据后端的预览基础路径拼接得到下载地址,并结合windwo.open 预览
- office文件类并且启用了office预览直接调用office预览路径(https://view.officeapps.live.com/op/view.aspx?src=)
html
<el-progress v-if="showProcessFlag&&processFlag" :percentage="loadProcess">el-progress>
js
onProgressFn(event, file, fileList){
this.processFlag = true
this.loadProcess = event.percent.toFixed(2)
if(this.loadProcess>=100){
this.loadProcess= 100
this.$nextTick(()=>{
this.processFlag = false
})
}
}
说明
- 用户启用了进度条(showProcessFlag为true) 并且 processFlag的值为true(当进度条的值存在并且小于100时)
- 当进度大于等于100时需要隐藏进度条,为了保险起见,此处加了 $nextTick,当然了setTimeout(()=>{},0)也可以
<template>
<div>
<!--action="/api/abk/web/v1/resource/file" -->
<el-upload
:action="actionUrl"
style="width: 100%"
:on-success="(response, file) => successUpload(response, file)"
:on-error="errorUpload"
:accept="acceptTypeList.join('|')"
:before-upload="beforeUpload"
:multiple="multiple"
:limit="maxLimit"
:on-exceed="handleExceed"
:file-list="fileList"
:disabled="disabledFlag"
:on-remove="(file, fileList) => removeFile(file, fileList)"
:on-preview="(file) => preview(file)"
:on-progress="(event, file, fileList)=>onProgressFn(event, file, fileList)"
>
<!-- 上传的按钮 或者 icon 通过具名插槽的方式 -->
<slot name="uploadBtn"></slot>
</el-upload>
<el-progress v-if="showProcessFlag&&processFlag" :percentage="loadProcess"></el-progress>
</div>
</template>
<script>
export default {
name: 'UploadFile',
props: {
actionUrl: {
//上传的地址
type: String,
default: '',
},
acceptTypeList: {
//接受的文件类型
type: Array,
default: () => {
return []
// ['doc', 'docx', 'xlsx', 'xls', 'txt', 'pdf','jpg','jpeg','png','zip,'rar']
},
},
multiple: {//是否开启多图上传
type: Boolean,
default: false,
},
maxLimit: {
// 最大上传个数限制
type: Number | String,
default: 1,
},
maxSize:{
// 文件上传的最大体积 M
type: Number | String,
default: 4,
},
disabledFlag: {
//是否禁用
type: Boolean,
default: false,
},
fileList: {//文件列表
type: Array,
default: () => {
return []
},
},
extraData: {}, //上传时的额外参数 如 name等
/*
{
name:'12321'
}
*/
dragFlag: {
type: Boolean,
default: true, //是否启用拖拽上传 此处默认启用 element 官方默认是 不启用的
},
downLoadTypeList: {
//需要下载的文件类型
type: Array,
default: () => {
return ['doc', 'docx', 'xlsx', 'xls', 'txt']
},
},
preveiwTypeList: {
//需要预览的文件类型
type: Array,
default: () => {
return ['pdf', 'jpg', 'jpeg', 'png']
},
},
officePreviewFlag: {
//是否启用office在线预览
type: Boolean,
default: false,
},
showProcessFlag:{
//是否显示进度条
type: Boolean,
default: false,
},
},
// office预览
// https://view.officeapps.live.com/op/view.aspx?src=
// https://view.officeapps.live.com/op/view.aspx?src=文档地址
//
data() {
return {
officeOnlineAddress:
'https://view.officeapps.live.com/op/view.aspx?src=',
officeType: ['doc', 'docx', 'xlsx', 'xls'],
processFlag:false,//是否显示进度条
loadProcess:0//进度条的刻度值
}
},
mounted() {},
methods: {
// 上传图片 成功
successUpload(response, file) {
if (response.rt.status === 200) {
this.fileList.push({
url: response.data,
name: file.name,
})
} else {
this.$Message.info(response.data)
}
},
errorUpload(res) {
this.$Message.info('上传失败请重试!')
},
beforeUpload(file) {
const { name = '', size } = file
if (size > this.maxSize * 1024 * 1000) {
this.$Message.warning(`文件最大仅支持${this.maxSize}M`)
return false
}
if (!this.acceptTypeList.includes(name.split('.').pop())) {
this.$Message.warning(
`文件格式仅支持${this.acceptTypeList.join(',')}`
)
return false
}
},
handleExceed(files, fileList) {
this.$Message.warning(
`当前限制选择 10 个文件,本次选择了 ${
files.length
} 个文件,共选择了 ${files.length + fileList.length} 个文件`
)
},
// 移除文件
removeFile(file, data) {
console.log(file, data)
this.fileList = data
},
// 预览
preview (data) {
const { url, response = {} } = data || {}
let name = data.name
const downLoadTypeList = this.downLoadTypeList
const preveiwTypeList = this.preveiwTypeList
if (!name) {
name = ''
}
const suffixFileType = name.split('.').pop()
if (downLoadTypeList.includes(suffixFileType)) {
//预览 'doc', 'docx', 'xlsx', 'xls', 'txt' 文件
name = name.replace(/&/g, '') // & 不兼容
const target = encodeURIComponent(
Base64.encode(
`${
location.origin
}/api/abk/web/v1/resource/file?fileId=${
url || response.data
}&fullfilename=${name}&sid=4AC67ADB4E264AB0A8B899A671072875`
)
)
if (
this.officePreviewFlag &&
this.officeType.includes(suffixFileType)
) {
// office预览的
const preveiewURL = this.officeOnlineAddress + target
window.open(preveiewURL)
} else {
// 非office预览
window.open(
`https://test/preview/onlinePreview?url=${target}`,
'_blank'
)
}
} else if (preveiwTypeList.includes(suffixFileType)) {
//新窗口打开 预览图片文件
window.open(
'/api/abk/web/v1/resource/file?fileId=' +
(url || response.data),
'_blank'
)
}
},
onProgressFn(event, file, fileList){
this.processFlag = true
this.loadProcess = event.percent.toFixed(2)
if(this.loadProcess>=100){
this.loadProcess= 100
this.$nextTick(()=>{
this.processFlag = false
})
}
}
},
}
</script>
<style lang="scss" scoped>
</style>
List){
this.processFlag = true
this.loadProcess = event.percent.toFixed(2)
if(this.loadProcess>=100){
this.loadProcess= 100
this.$nextTick(()=>{
this.processFlag = false
})
}
}
},
}
</script>
<style lang="scss" scoped>
</style>