Upload 上传 预览功能
16:20该组件用于上传文件场景,支持图片、视频、文档等多种类型,支持网格(grid)和列表(list)两种展示模式
平台差异说明
| App | H5 | 微信小程序 | 支付宝小程序 | 百度小程序 | 头条小程序 | QQ小程序 |
|---|---|---|---|---|---|---|
| √ | √ | √ | √ | √ | √ | √ |
特殊说明:
accept="file"仅在 H5 和微信小程序支持accept="media"仅在微信小程序、支付宝小程序、App 支持- 文件预览功能在 H5 支持最好,其他平台可能受限于系统能力
基本使用
- 可以通过设置
file-list参数(数组,元素为对象),显示预置的文件。其中元素的url属性为文件路径 - 设置
action参数为后端服务器地址,注意H5在浏览器可能会有跨域限制,让后端允许域即可 - 默认
accept="image",只支持图片上传
<template>
<u-upload :action="action" :file-list="fileList" ></u-upload>
</template>
<script setup lang="ts">
// 演示地址,请勿直接使用
import { ref } from 'vue'
const action = ref('http://www.example.com/upload')
const fileList = ref([
{
url: 'http://pics.sc.chinaz.com/files/pic/pic9/201912/hpic1886.jpg',
}
])
</script>上传多种文件类型
通过设置accept参数,可以上传不同类型的文件:
image- 图片(默认)video- 视频file- 文件(仅H5、微信小程序支持)media- 媒体文件(图片+视频,仅部分平台支持)all- 所有文件
<!-- 上传视频 -->
<u-upload :action="action" accept="video" :max-duration="120"></u-upload>
<!-- 上传文件(H5/微信小程序) -->
<u-upload :action="action" accept="file" :extension="['.pdf', '.docx']"></u-upload>
<!-- 上传所有类型 -->
<u-upload :action="action" accept="all"></u-upload>展示模式
组件支持两种展示模式,通过mode参数设置:
grid- 网格模式(默认),适合图片展示list- 列表模式,适合文件展示,显示文件名和大小
<!-- 网格模式(默认) -->
<u-upload :action="action" accept="image" mode="grid"></u-upload>
<!-- 列表模式 -->
<u-upload :action="action" accept="file" mode="list" :show-file-name="true" :show-file-size="true"></u-upload>手动上传
组件默认为自动上传,可以设置auto-upload为false,然后通过ref调用组件的upload方法,手动上传文件
<!-- 手动上传 -->
<template>
<view>
<u-upload ref="uUploadRef" :action="action" :auto-upload="false" ></u-upload>
<u-button @click="submit">提交</u-button>
</view>
</template>
<script setup lang="ts">
// 非真实地址
import { ref } from 'vue'
const action = ref('http://www.example.com/upload')
const uUploadRef = ref()
function submit() {
uUploadRef.value?.upload()
}
</script>获取上传的文件列表
文件选择或者上传成功后,会保存在组件内部的lists数组中,数组元素为对象,有如下属性:
url: 文件地址name: 文件名size: 文件大小(字节)fileType: 文件类型(image/video/file)error:上传失败标记progress:上传进度,0-100,100表示上传成功response:上传成功后,服务器返回的数据
为了获得上传的文件列表,可以在提交表单时,通过ref获取组件内部的lists文件数组,筛选出progress为100的文件
<!-- 获取上传的文件列表 -->
<template>
<view>
<u-upload ref="uUploadRef" :action="action" :auto-upload="true" ></u-upload>
<u-button @click="submit">提交</u-button>
</view>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const action = ref('http://www.example.com/upload')
const uUploadRef = ref()
function submit() {
let files = []
// 通过filter,筛选出上传进度为100的文件(因为某些上传失败的文件,进度值不为100,这个是可选的操作)
files = uUploadRef.value?.lists.filter((val: any) => {
return val.progress == 100
})
// 如果您不需要进行太多的处理,直接如下即可
// files = uUploadRef.value?.lists
console.log(files)
}
</script>报错提示
在以下几种情况,组件会默认通过toast提示用户信息,可以把show-tips设置为false取消默认的提示,这时可以通过API 中的各种事件,进行自定义的个性化提示
- 超出允许的最大上传数量
- 文件大小超出最大允许大小
- 上传文件出错
- 移除文件
以下示例为屏蔽组件内部的提示,在移除文件时,监听onRemove事件,手动提示的情况
<!-- 屏蔽组件内部的提示,在移除文件时,监听onRemove事件,手动提示的情况 -->
<template>
<u-upload ref="uUploadRef" :action="action" :show-tips="false" @on-remove="onRemove"></u-upload>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const action = ref('http://www.example.com/upload')
const uUploadRef = ref()
function onRemove(index: number, lists: any[]) {
console.log('文件已被移除')
}
</script>限制文件数量和大小
- 通过
max-count可以设置最多可以选择的文件的数量 - 通过
max-size设置单个文件最大的大小,单位为B(byte),默认不限制
下方示例为单张最大为5M,最多选择6个文件的情况:
<u-upload :max-size="5 * 1024 * 1024" max-count="6"></u-upload>限制文件类型
可以通过以下方式限制文件类型:
accept参数 - 基础文件类型限制(image/video/file/media/all)limit-type参数 - 详细的文件后缀限制,优先级最高extension参数 - 仅在 H5 和微信小程序accept="file"时有效,用于系统文件选择器过滤
<!-- 方式1:限制为图片 -->
<u-upload accept="image"></u-upload>
<!-- 方式2:详细限制后缀(推荐) -->
<u-upload accept="image" :limit-type="['png', 'jpg', 'jpeg']"></u-upload>
<!-- 方式3:H5/微信小程序选择PDF和Word -->
<u-upload accept="file" :extension="['.pdf', '.docx']" :limit-type="['pdf', 'docx']"></u-upload>上传前的钩子
某些时候,每个文件上传前可能需要动态修改文件名,修改额外参数等,就会需要用到一个叫before-upload的钩子(参数注意不要加括号),也即回调方法,此方法会返回两个参数:
index——即当前上传文件在上传列表中的索引lists——当前所有的文件列表
此回调可以返回一个promise、true,或者false,下面分别阐述三者的处理情况:
false——如果返回false,将会跳过当前文件,继续上传下一个文件(如果有),并且再次执行before-upload钩子true——如果返回true,会随即上传当前文件,上传成功后,继续上传下一个文件(如果有),并且再次执行before-upload钩子promise——如果返回的是一个promise,如果进入then回调,就会和返回true的情况一样,如果进入catch回调,就会和返回false的情况一样
下面举例说明:
1. 普通返回
<!-- before-upload 普通返回 -->
<template>
<u-upload :before-upload="beforeUpload"></u-upload>
</template>
<script setup lang="ts">
function beforeUpload(index: number, list: any[]) {
// 只上传偶数索引的文件
if(index % 2 == 0) return true;
else return false;
}
</script>2. 请求之后再返回
<!-- before-upload 请求之后再返回 -->
<template>
<u-upload :before-upload="beforeUpload"></u-upload>
</template>
<script setup lang="ts">
async function beforeUpload(index: number, list: any[]) {
// await等待一个请求,请求回来后再返回true,继续上传文件
let data = await uni.$u.post('url');
return true; // 或者根据逻辑返回false
}
</script>3. 返回一个Promise
<!-- before-upload 返回一个Promise -->
<template>
<u-upload :before-upload="beforeUpload"></u-upload>
</template>
<script setup lang="ts">
function beforeUpload(index: number, list: any[]) {
// 返回一个promise
return new Promise((resolve, reject) => {
uni.$u.post('url').then(res => {
// resolve()之后,将会进入promise的组件内部的then回调,相当于返回true
resolve();
}).catch(err => {
// reject()之后,将会进入promise的组件内部的catch回调,相当于返回false
reject();
})
})
}
</script>移除前的钩子
某些时候,文件被移除前可能需要进行判断是否可以被移除,就会需要用到一个叫before-remove的钩子(参数注意不要加括号),也即回调方法,此方法会返回两个参数:
index——即当前上传文件在上传列表中的索引lists——当前所有的文件列表
此回调可以返回一个promise、true,或者false,下面分别阐述三者的处理情况:
false——如果返回false,终止移除操作true——如果返回true,执行移除操作promise——如果返回的是一个promise,如果进入then回调,就会和返回true的情况一样,如果进入catch回调,就会和返回false的情况一样
此处不举例说明,参考before-upload的示例即可。
删除确认弹窗
默认情况下,删除文件前会显示确认弹窗。可以通过show-confirm参数控制:
<!-- 不显示删除确认弹窗 -->
<u-upload :action="action" :show-confirm="false"></u-upload>自定义相关说明
组件内部样式
组件默认选取文件会展示预览缩略图,包括默认的选取文件的按钮,他们的宽高都是200rpx,border-radius值为10rpx, 另外预览图片的盒子有一个默认的边框,值为border: 1px solid rgb(235, 236, 238)。如果用户需要自定义上传按钮,可以参考这些值。自定义上传按钮
通过传递名为addBtn的slot,同时配置custom-btn为true,可以自定义想要的上传按钮。
如下所示:
<u-upload :custom-btn="true">
<template #addBtn>
<view class="slot-btn" hover-class="slot-btn__hover" hover-stay-time="150">
<u-icon name="photo" size="60" color="#2979ff"></u-icon>
</view>
</template>
</u-upload>
<style>
.slot-btn {
width: 329rpx;
height: 140rpx;
display: flex;
justify-content: center;
align-items: center;
background: rgb(244, 245, 246);
border-radius: 10rpx;
}
.slot-btn__hover {
background-color: rgb(235, 236, 238);
}
</style>- 自定义预览列表 首先需要设置
show-upload-list为false来去除组件内部的默认预览列表,其次需要通过ref获取组件,进而 操作组件内部的变量和方法,下面为一些组件内部的方法和变量说明:
lists(变量),可以通过此值,构建自定义的预览列表,该变量内部如下:
lists = [
{
url: 'xxx.png', // 预览文件的地址
name: 'xxx.png', // 文件名
size: 1024, // 文件大小(字节)
fileType: 'image', // 文件类型
error: false, // 上传失败,此值为true
progress: 100, // 0-100之间的值
},
......
]deleteItem(index)(方法),可以用此方法在自定义列表中通过ref删除某一个文件
以下为完整的自定义文件预览列表示例:
<!-- 自定义文件预览列表 -->
<template>
<view class="wrap">
<view class="pre-box" v-if="!showUploadList">
<view class="pre-item" v-for="(item, index) in lists" :key="index">
<image class="pre-item-image" :src="item.url" mode="aspectFill"></image>
</view>
</view>
<u-upload :custom-btn="true" ref="uUploadRef" :show-upload-list="showUploadList" :action="action">
<template #addBtn>
<view class="slot-btn" hover-class="slot-btn__hover" hover-stay-time="150">
<u-icon name="photo" size="60" color="#c0c4cc"></u-icon>
</view>
</template>
</u-upload>
</view>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
const action = ref('http://www.example.com') // 演示地址
const showUploadList = ref(false)
const uUploadRef = ref()
const lists = ref<any[]>([])
// 只有onMounted生命周期才能调用refs操作组件
onMounted(() => {
// 得到整个组件对象,内部文件列表变量为"lists"
lists.value = uUploadRef.value?.lists || []
})
</script>
<style lang="scss">
.wrap {
padding: 24rpx;
}
.slot-btn {
width: 341rpx;
height: 140rpx;
display: flex;
justify-content: center;
align-items: center;
background: rgb(244, 245, 246);
border-radius: 10rpx;
}
.slot-btn__hover {
background-color: rgb(235, 236, 238);
}
.pre-box {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
}
.pre-item {
flex: 0 0 48.5%;
border-radius: 10rpx;
height: 140rpx;
overflow: hidden;
position: relative;
margin-bottom: 20rpx;
}
.pre-item-image {
width: 100%;
height: 140rpx;
}
</style>API
Props
| 参数 | 说明 | 类型 | 默认值 | 可选值 | 版本 |
|---|---|---|---|---|---|
| action | 服务器上传地址 | String | - | - | - |
| accept | 接受的文件类型 | String | image | image / video / file / media / all | 0.5.19 |
| mode | 展示模式 | String | grid | grid / list | 0.5.19 |
| max-count | 最大选择文件的数量 | String | Number | 52 | - | - |
| max-size | 选择单个文件的最大大小,单位B(byte) | String | Number | Number.MAX_VALUE | - | - |
| width | 预览区域和添加按钮的宽度,单位rpx | String | Number | 200 | - | - |
| height | 预览区域和添加按钮的高度,单位rpx | String | Number | 200 | - | - |
| multiple | 是否开启文件多选 | Boolean | true | true / false | - |
| disabled | 是否禁用组件 | Boolean | false | true / false | - |
| auto-upload | 选择完文件是否自动上传 | Boolean | true | true / false | - |
| deletable | 是否显示删除文件的按钮 | Boolean | true | true / false | - |
| show-confirm | 删除文件前是否显示确认弹窗 | Boolean | true | true / false | 0.5.19 |
| show-tips | 特殊情况下是否自动提示toast | Boolean | true | true / false | - |
| show-progress | 是否显示上传进度条 | Boolean | true | true / false | - |
| show-upload-list | 是否显示组件内部的文件预览列表 | Boolean | true | true / false | - |
| show-file-name | 是否显示文件名 | Boolean | true | true / false | 0.5.19 |
| show-file-size | 是否显示文件大小 | Boolean | false | true / false | 0.5.19 |
| preview-full-image | 是否可以通过uni.previewImage预览已选择的图片 | Boolean | true | true / false | - |
| preview-file | 是否可预览文件(非图片类型) | Boolean | true | true / false | 0.5.19 |
| custom-btn | 是否自定义选择文件的按钮 | Boolean | false | true / false | - |
| upload-text | 选择文件按钮的提示文字 | String | 根据accept自动显示 | - | - |
| image-mode | 预览图片的显示模式 | String | aspectFill | - | - |
| del-icon | 右上角删除图标名称 | String | close | - | - |
| del-bg-color | 右上角删除按钮的背景颜色 | String | var(--u-type-error) | - | - |
| del-color | 右上角删除按钮图标的颜色 | String | var(--u-white-color) | - | - |
| header | 上传携带的请求头信息 | Object | {} | - | - |
| form-data | 上传额外携带的参数 | Object | {} | - | - |
| name | 上传文件的字段名 | String | file | - | - |
| size-type | original 原图,compressed 压缩图 | Array<String> | ['original', 'compressed'] | - | - |
| source-type | 选择文件的来源,album-相册,camera-相机 | Array<String> | ['album', 'camera'] | - | - |
| limit-type | 限制允许上传的文件后缀,优先级高于accept | Array<String> | [] | - | - |
| extension | 选择文件时的扩展名过滤,仅H5和微信小程序有效 | Array<String> | [] | - | 0.5.19 |
| file-icon-map | 文件类型图标映射配置 | Object | {} | - | 0.5.19 |
| file-list | 默认显示的文件列表 | Array<Object> | [] | - | - |
| compressed | 选择视频时是否压缩 | Boolean | true | true / false | 0.5.19 |
| max-duration | 选择视频时拍摄最长时长,单位秒 | Number | 60 | - | 0.5.19 |
| camera | 选择视频时摄像头方向 | String | back | front / back | 0.5.19 |
| before-upload | 上传前钩子 | Function | - | - | - |
| before-remove | 删除前钩子 | Function | - | - | - |
| to-json | 如果上传后返回值为json字符串,是否自动转为json | Boolean | true | true / false | - |
| index | 在各个回调事件中的最后一个参数返回,用于区别是哪一个组件的事件 | String | Number | - | - | - |
Methods
此方法如要通过ref手动调用
| 名称 | 说明 | 版本 |
|---|---|---|
| upload | 手动上传文件 | - |
| clear | 清空内部文件列表 | - |
| reUpload | 重新上传所有失败/未上传的文件 | - |
| retry(index) | 重新上传指定索引的文件 | - |
| remove(index) | 手动移除指定索引的文件 | - |
| selectFile | 手动触发文件选择 | - |
| doPreviewImage(url, index) | 预览图片 | - |
| doPreviewFile(item, index) | 预览/打开文件 | 0.5.19 |
Slots
| 名称 | 说明 | 版本 |
|---|---|---|
| addBtn | 自定义选择文件按钮 | - |
| file | 自定义文件列表插槽 | - |
Events
回调参数中的lists参数,为目前组件内的所有文件数组,index为当前操作的文件的索引,name为通过props传递的index参数:
| 事件名 | 说明 | 回调参数 | 版本 |
|---|---|---|---|
| on-oversize | 文件大小超出max-size限制时触发 | (file, lists, name) | - |
| on-exceed | 文件数量超出max-count限制时触发 | (file, lists, name) | - |
| on-choose-complete | 每次选择文件后触发 | (lists, name) | - |
| on-choose-fail | 文件选择失败时触发 | (error) | - |
| on-uploaded | 所有文件上传完毕触发 | (lists, name) | - |
| on-success | 单个文件上传成功时触发 | (data, index, lists, name) | - |
| on-error | 单个文件上传失败时触发 | (res, index, lists, name) | - |
| on-change | 单个文件上传状态改变时触发 | (res, index, lists, name) | - |
| on-progress | 文件上传过程中的进度变化时触发 | (res, index, lists, name) | - |
| on-remove | 移除文件时触发 | (index, lists, name) | - |
| on-preview | 预览文件时触发 | (url, lists, name) | - |
| on-list-change | 文件列表发生变化时触发 | (lists, name) | - |
