Skip to content

Upload 上传 预览功能

16:20

该组件用于上传文件场景,支持图片、视频、文档等多种类型,支持网格(grid)和列表(list)两种展示模式

平台差异说明

AppH5微信小程序支付宝小程序百度小程序头条小程序QQ小程序

特殊说明:

  • accept="file" 仅在 H5 和微信小程序支持
  • accept="media" 仅在微信小程序、支付宝小程序、App 支持
  • 文件预览功能在 H5 支持最好,其他平台可能受限于系统能力

基本使用

  • 可以通过设置file-list参数(数组,元素为对象),显示预置的文件。其中元素的url属性为文件路径
  • 设置action参数为后端服务器地址,注意H5在浏览器可能会有跨域限制,让后端允许域即可
  • 默认accept="image",只支持图片上传
html
<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 - 所有文件
html
<!-- 上传视频 -->
<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 - 列表模式,适合文件展示,显示文件名和大小
html
<!-- 网格模式(默认) -->
<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-uploadfalse,然后通过ref调用组件的upload方法,手动上传文件

html
<!-- 手动上传 -->
<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的文件

html
<!-- 获取上传的文件列表 -->
<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事件,手动提示的情况

html
<!-- 屏蔽组件内部的提示,在移除文件时,监听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个文件的情况:

html
<u-upload :max-size="5 * 1024 * 1024" max-count="6"></u-upload>

限制文件类型

可以通过以下方式限制文件类型:

  1. accept参数 - 基础文件类型限制(image/video/file/media/all)
  2. limit-type参数 - 详细的文件后缀限制,优先级最高
  3. extension参数 - 仅在 H5 和微信小程序 accept="file" 时有效,用于系统文件选择器过滤
html
<!-- 方式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——当前所有的文件列表

此回调可以返回一个promisetrue,或者false,下面分别阐述三者的处理情况:

  • false——如果返回false,将会跳过当前文件,继续上传下一个文件(如果有),并且再次执行before-upload钩子
  • true——如果返回true,会随即上传当前文件,上传成功后,继续上传下一个文件(如果有),并且再次执行before-upload钩子
  • promise——如果返回的是一个promise,如果进入then回调,就会和返回true的情况一样,如果进入catch回调,就会和返回false的情况一样

下面举例说明:

1. 普通返回

html
<!-- 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. 请求之后再返回

html
<!-- 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

html
<!-- 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——当前所有的文件列表

此回调可以返回一个promisetrue,或者false,下面分别阐述三者的处理情况:

  • false——如果返回false,终止移除操作
  • true——如果返回true,执行移除操作
  • promise——如果返回的是一个promise,如果进入then回调,就会和返回true的情况一样,如果进入catch回调,就会和返回false的情况一样

此处不举例说明,参考before-upload的示例即可。

删除确认弹窗

默认情况下,删除文件前会显示确认弹窗。可以通过show-confirm参数控制:

html
<!-- 不显示删除确认弹窗 -->
<u-upload :action="action" :show-confirm="false"></u-upload>

自定义相关说明

  1. 组件内部样式
    组件默认选取文件会展示预览缩略图,包括默认的选取文件的按钮,他们的宽高都是200rpxborder-radius值为10rpx, 另外预览图片的盒子有一个默认的边框,值为border: 1px solid rgb(235, 236, 238)。如果用户需要自定义上传按钮,可以参考这些值。

  2. 自定义上传按钮
    通过传递名为addBtnslot,同时配置custom-btntrue,可以自定义想要的上传按钮。

如下所示:

html
<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>
  1. 自定义预览列表 首先需要设置show-upload-listfalse来去除组件内部的默认预览列表,其次需要通过ref获取组件,进而 操作组件内部的变量和方法,下面为一些组件内部的方法和变量说明:
  • lists(变量),可以通过此值,构建自定义的预览列表,该变量内部如下:
js
lists = [
	{
		url: 'xxx.png', // 预览文件的地址
		name: 'xxx.png', // 文件名
		size: 1024, // 文件大小(字节)
		fileType: 'image', // 文件类型
		error: false, // 上传失败,此值为true
		progress: 100, // 0-100之间的值
	},
	......
]
  • deleteItem(index)(方法),可以用此方法在自定义列表中通过ref删除某一个文件

以下为完整的自定义文件预览列表示例:

html
<!-- 自定义文件预览列表 -->
<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接受的文件类型Stringimageimage / video / file / media / all0.5.19
mode展示模式Stringgridgrid / list0.5.19
max-count最大选择文件的数量String | Number52--
max-size选择单个文件的最大大小,单位B(byte)String | NumberNumber.MAX_VALUE--
width预览区域和添加按钮的宽度,单位rpxString | Number200--
height预览区域和添加按钮的高度,单位rpxString | Number200--
multiple是否开启文件多选Booleantruetrue / false-
disabled是否禁用组件Booleanfalsetrue / false-
auto-upload选择完文件是否自动上传Booleantruetrue / false-
deletable是否显示删除文件的按钮Booleantruetrue / false-
show-confirm删除文件前是否显示确认弹窗Booleantruetrue / false0.5.19
show-tips特殊情况下是否自动提示toastBooleantruetrue / false-
show-progress是否显示上传进度条Booleantruetrue / false-
show-upload-list是否显示组件内部的文件预览列表Booleantruetrue / false-
show-file-name是否显示文件名Booleantruetrue / false0.5.19
show-file-size是否显示文件大小Booleanfalsetrue / false0.5.19
preview-full-image是否可以通过uni.previewImage预览已选择的图片Booleantruetrue / false-
preview-file是否可预览文件(非图片类型)Booleantruetrue / false0.5.19
custom-btn是否自定义选择文件的按钮Booleanfalsetrue / false-
upload-text选择文件按钮的提示文字String根据accept自动显示--
image-mode预览图片的显示模式StringaspectFill--
del-icon右上角删除图标名称Stringclose--
del-bg-color右上角删除按钮的背景颜色Stringvar(--u-type-error)--
del-color右上角删除按钮图标的颜色Stringvar(--u-white-color)--
header上传携带的请求头信息Object{}--
form-data上传额外携带的参数Object{}--
name上传文件的字段名Stringfile--
size-typeoriginal 原图,compressed 压缩图Array<String>['original', 'compressed']--
source-type选择文件的来源,album-相册,camera-相机Array<String>['album', 'camera']--
limit-type限制允许上传的文件后缀,优先级高于acceptArray<String>[]--
extension选择文件时的扩展名过滤,仅H5和微信小程序有效Array<String>[]-0.5.19
file-icon-map文件类型图标映射配置Object{}-0.5.19
file-list默认显示的文件列表Array<Object>[]--
compressed选择视频时是否压缩Booleantruetrue / false0.5.19
max-duration选择视频时拍摄最长时长,单位秒Number60-0.5.19
camera选择视频时摄像头方向Stringbackfront / back0.5.19
before-upload上传前钩子Function---
before-remove删除前钩子Function---
to-json如果上传后返回值为json字符串,是否自动转为jsonBooleantruetrue / 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)-

最后更新于: