分享一个自己封装的基于iview的Upload组件,支持图片及文档的在线预览,支持图片的压缩上传(仅本地),同时整合七牛云、腾讯云(不支持压缩),上传文件类型不限,有需要的可以拿去使用,写的不好请勿喷。
组件是一个上传集合所以代码有点多,使用时建议拆分为自己项目需要的那部分。
图片压缩原理:浏览器从本地读取到文件并构造成一个image对象,然后把image对象根据自己需要的大小裁剪为指定宽高(默认宽度1920)后填充到canvas中,最终通过canvas.toDataURL(type,quantity)函数配置图片类型和质量得到文件的base64字符串。此时可以将base64转blob使用formData上传,本组件未使用此方法,而是直接上传base64字符串由服务后台转图片。
package.json, 必须的包如下:
"axios": "^0.18.0", //通过https获取对应的上传token
"cos-js-sdk-v5": "^0.5.17", //cos
"qiniu-js": "^2.5.4", //qiniu
组件属性说明:
value | Array/String | v-model绑定 |
max-size | Number | 上传文件大小,默认2Mb |
multiple | Boolean | 是否可以多选文件上传 |
readonly | Boolean | 是否只读模式,为true则不可上传 |
type | String | 上传文件类型 image/video/audio/pdf/wps,不传表示任意类型 |
tips | String | 上传提示文本 |
length | Number | 总的最大上传文件个数 |
compressed | Boolean | 是否压缩,仅type='image'时支持压缩,此时不能使用七牛、腾讯云上传 |
mode | String | 空-后台服务上传、 cos-腾讯云 、qiniu-七牛云 |
使用示例:
<ExtUpload v-model="formItem.img" type="image" :compressed="true"></ExtUpload>
<ExtUpload type="wps" :max-size="10240" v-model="formItem.files" :multiple="true" mode='cos' :length='6'></ExtUpload>
<style scoped lang="less">
@import '../../../theme/index.less';
.remove-btn {
position: absolute;
/*top: -10px;*/
right: -5px;
color: #FE526A;
cursor: pointer;
z-index: 100;
display: none;
}
.upload-image {
width: 80px;
height: 80px;
margin-top: 10px;
}
.upload-btn {
width: 60px;
height: 60px;
line-height: 60px;
text-align: center;
border: 1px dashed #dddddd;
border-radius: 2px;
cursor: pointer;
}
.demo-spin-icon-load {
animation: ani-demo-spin 1s linear infinite;
}
.tips {
position: absolute;
font-size: 10px;
color: #FE526A;
display: inline-block;
bottom: -20px;
}
.img-wrap{
margin-right: 15px;
}
.img-wrap:hover .remove-btn {
display: inline-block;
}
.taglist {
display: inline-block;
border: none;
cursor: pointer;
margin-right: 15px;
}
.taglist span {
color: @link-color;
cursor: pointer;
}
.taglist:hover .remove-btn {
display: inline-block;
}
</style>
<template>
<div style="display:flex;align-items:center;min-width: 200px;">
<canvas id="canvasId" style="display: none;"></canvas>
<div>
<div v-if="type!=='image'" class="taglist" v-for="(item,idx) in files" :key="idx"
style="position:relative;display:inline-block">
<span @click="preview(item)">{
{item.name||item.url}}</span>
<span class="remove-btn" v-if="!readonly">
<Icon @click.native="deleteItem(idx)" type="ios-close-circle" color="red" size="20"/>
</span>
</div>
<div v-if="type==='image'" style="display: flex;flex-wrap: wrap">
<div class="img-wrap" v-for="(item,idx) in images" :key="idx"
style="position:relative;display:inline-block">
<img :src="item|fmtUrl" class="upload-image" @click="preview(item)"/>
<span class="remove-btn" v-if="!readonly">
<Icon @click.native="deleteItem(idx)" type="ios-close-cir