Upload 
组件类型:UxUploadComponentPublicInstance
支持图片视频,支持删除、排序功能,支持进度显示
平台兼容性 
UniApp X 
| Android | iOS | web | 鸿蒙 Next | 小程序 | 
|---|---|---|---|---|
| √ | √ | √ | √ | √ | 
UniApp Vue Nvue 
| Android | iOS | web | 鸿蒙 Next | 小程序 | 
|---|---|---|---|---|
| x | x | √ | x | x | 
Props 
| 属性名 | 类型 | 默认值 | 说明 | 
|---|---|---|---|
| list | Array | 默认列表 | |
| name | String | file | 文件对应的key,开发者在服务器端通过这个key可以获取到文件二进制内容 | 
| url | String | 上传地址 | |
| header | UTSJSONObject | HTTP请求Header,header中不能设置Referer | |
| formData | UTSJSONObject | HTTP请求中其他额外的formdata | |
| timeout | Number | 120000 | 超时时间,单位ms | 
| retry | Number | 3 | 重试次数 | 
| successCode | Number | 200 | 上传成功状态码 | 
| mode | String | image | 模式 | 
| count | Number | 9 | 最大数量 | 
| sizeType | Array | ['original','compressed'] | original原图,compressed压缩图Web不支持 | 
| sourceType | Array | ['album','camera'] | album从相册选图,camera使用相机 | 
| extension | Array | 文件拓展名过滤仅Web支持 | |
| align | String | left | 对齐方向 | 
| rows | Boolean | true | 多行 | 
| col | Number | 4 | 列数,rows=true时生效 | 
| gutter | Any | 间隔默认5) | |
| width | Any | 65 | 文件宽,rows=false时生效 | 
| height | Any | 65 | 文件高,rows=false时生效 | 
| radius | Any | 8 | 圆角 | 
| background | String | 按钮背景色 | |
| backgroundDark | String | 深色none-不显示,auto-自动适配深色模式,其他-颜色 | |
| borderColor | String | 按钮边框色 | |
| borderColorDark | String | 深色none-不显示,auto-自动适配深色模式,其他-颜色 | |
| waitingText | String | 等待上传 | 等待上传文案 | 
| failText | String | 上传失败 | 等待失败文案 | 
| frontBtn | Boolean | false | 前置上传按钮 | 
| showDel | Boolean | true | 显示删除按钮 | 
| beforeDel | Function | 删除钩子 | |
| beforeUpload | Function | 上传前钩子 | |
| afterUpload | Function | 上传完成钩子 | |
| autoUpload | Boolean | true | 自动上传 | 
| disabled | Boolean | false | 禁用 | 
mode 
| 值 | 说明 | 
|---|---|
| image图片 | |
| video视频 | |
| media媒体 | |
| file文件 | 
align 
| 值 | 说明 | 
|---|---|
| left居左 | |
| right居右 | 
backgroundDark 
| 值 | 说明 | 
|---|---|
| none不显示 | |
| auto自动适配深色模式 | |
| color其他颜色 | 
borderColorDark 
| 值 | 说明 | 
|---|---|
| none不显示 | |
| auto自动适配深色模式 | |
| color其他颜色 | 
Events 
| 事件名 | 说明 | 参数 | 
|---|---|---|
| click | 点击时触发 | |
| change | 值改变时触发 | |
| error | 发生错误时触发 | 
示例代码 
html
<template>
	<ux-page :stack="showDoc">
		<ux-navbar :title="title" :bold="true">
			<template v-slot:right>
				<!-- #ifndef MP -->
				<ux-button theme="text" icon="/static/tip.png" :icon-size="22" @click="onDoc()"></ux-button>
				<!-- #endif -->
			</template>
		</ux-navbar>
		
		<ux-scroll>
			<ux-card direction="column" icon="flag-filled" title="上传" :bold="true">
				<ux-text text="支持图片视频、支持宫格、单行滚动显示,支持手动提交上传"></ux-text>
			</ux-card>
			
			<ux-card direction="column" icon="arrowright" title="上传图片" :bold="true">
				<ux-text text="支持宫格显示" :mb="15"></ux-text>
				<ux-upload :list="files1" :after-upload="afterUpload" :before-del="beforeDel" :url="url" mode="image" @click="onPreview" @change="change1"></ux-upload>
			</ux-card>
			
			<ux-card direction="column" icon="arrowright" title="上传视频" :bold="true">
				<ux-text text="支持配置视频缩略图显示" :mb="15"></ux-text>
				<ux-upload :list="files2" :after-upload="afterUpload" :before-del="beforeDel" :url="url" mode="video" @click="onPreview" @change="change2"></ux-upload>
			</ux-card>
			
			<ux-card direction="column" icon="arrowright" title="上传媒体" :bold="true">
				<ux-text text="支持上传按钮前置, 支持单行滚动显示" :mb="15"></ux-text>
				<ux-upload :front-btn="true" :list="files3" :before-upload="beforeUpload" :after-upload="afterUpload" :before-del="beforeDel" :url="url" mode="media" :rows="false" @click="onPreview" @change="change3"></ux-upload>
			</ux-card>
			
			<ux-card direction="column" icon="arrowright" title="手动上传" :bold="true">
				<ux-upload ref="uxUploadRef" :auto-upload="false" :front-btn="true" :list="files4" :after-upload="afterUpload" :before-del="beforeDel" :url="url" mode="image" @click="onPreview" @change="change4"></ux-upload>
				<ux-button :mt="15" theme="primary" text="点击上传" @click="submit"></ux-button>
			</ux-card>
			
			<ux-card direction="column" icon="arrowright" title="表单数据" :bold="true">
				<ux-text text="支持传入 header、formData" :mb="15"></ux-text>
				<ux-upload :form-data="formData" :success-code="204" :list="files5" :before-del="beforeDel" :url="url2" mode="image"  @click="onPreview" @change="change5"></ux-upload>
			</ux-card>
			
			<ux-card direction="column" icon="arrowright" title="上传文件" :bold="true">
				<ux-text text="暂不支持上文件上传" :mb="15"></ux-text>
				<ux-upload mode="file" @error="error"></ux-upload>
			</ux-card>
			
			<ux-placeholder :height="200">
				<ux-row justify="center" align="center" style="height: 100%;">
					<ux-text prefix-icon="soapbubble-filled" text="真的没有了~"></ux-text>
				</ux-row>
			</ux-placeholder>
		</ux-scroll>
	</ux-page>
</template><template>
	<ux-page :stack="showDoc">
		<ux-navbar :title="title" :bold="true">
			<template v-slot:right>
				<!-- #ifndef MP -->
				<ux-button theme="text" icon="/static/tip.png" :icon-size="22" @click="onDoc()"></ux-button>
				<!-- #endif -->
			</template>
		</ux-navbar>
		
		<ux-scroll>
			<ux-card direction="column" icon="flag-filled" title="上传" :bold="true">
				<ux-text text="支持图片视频、支持宫格、单行滚动显示,支持手动提交上传"></ux-text>
			</ux-card>
			
			<ux-card direction="column" icon="arrowright" title="上传图片" :bold="true">
				<ux-text text="支持宫格显示" :mb="15"></ux-text>
				<ux-upload :list="files1" :after-upload="afterUpload" :before-del="beforeDel" :url="url" mode="image" @click="onPreview" @change="change1"></ux-upload>
			</ux-card>
			
			<ux-card direction="column" icon="arrowright" title="上传视频" :bold="true">
				<ux-text text="支持配置视频缩略图显示" :mb="15"></ux-text>
				<ux-upload :list="files2" :after-upload="afterUpload" :before-del="beforeDel" :url="url" mode="video" @click="onPreview" @change="change2"></ux-upload>
			</ux-card>
			
			<ux-card direction="column" icon="arrowright" title="上传媒体" :bold="true">
				<ux-text text="支持上传按钮前置, 支持单行滚动显示" :mb="15"></ux-text>
				<ux-upload :front-btn="true" :list="files3" :before-upload="beforeUpload" :after-upload="afterUpload" :before-del="beforeDel" :url="url" mode="media" :rows="false" @click="onPreview" @change="change3"></ux-upload>
			</ux-card>
			
			<ux-card direction="column" icon="arrowright" title="手动上传" :bold="true">
				<ux-upload ref="uxUploadRef" :auto-upload="false" :front-btn="true" :list="files4" :after-upload="afterUpload" :before-del="beforeDel" :url="url" mode="image" @click="onPreview" @change="change4"></ux-upload>
				<ux-button :mt="15" theme="primary" text="点击上传" @click="submit"></ux-button>
			</ux-card>
			
			<ux-card direction="column" icon="arrowright" title="表单数据" :bold="true">
				<ux-text text="支持传入 header、formData" :mb="15"></ux-text>
				<ux-upload :form-data="formData" :success-code="204" :list="files5" :before-del="beforeDel" :url="url2" mode="image"  @click="onPreview" @change="change5"></ux-upload>
			</ux-card>
			
			<ux-card direction="column" icon="arrowright" title="上传文件" :bold="true">
				<ux-text text="暂不支持上文件上传" :mb="15"></ux-text>
				<ux-upload mode="file" @error="error"></ux-upload>
			</ux-card>
			
			<ux-placeholder :height="200">
				<ux-row justify="center" align="center" style="height: 100%;">
					<ux-text prefix-icon="soapbubble-filled" text="真的没有了~"></ux-text>
				</ux-row>
			</ux-placeholder>
		</ux-scroll>
	</ux-page>
</template>ts
<script setup>
	
	import * as plus from '@/uni_modules/ux-plus'
	import { UxUploadFile } from '@/uni_modules/ux-frame';
	
	const title = ref('')
	
	const uxUploadRef = ref<UxUploadComponentPublicInstance | null>(null)
	
	const url = 'https://test.api.fdproxy.cn/file/upload/add'
	
	const url2 = 'http://jxqft.com:9000/shaokx'
	
	const files1 = ref<UTSJSONObject[]>([{
		id: '1',
		url: 'http://gips0.baidu.com/it/u=1690853528,2506870245&fm=3028&app=3028&f=JPEG&fmt=auto?w=1024&h=1024'
	},{
		id: '2',
		url: 'http://gips2.baidu.com/it/u=195724436,3554684702&fm=3028&app=3028&f=JPEG&fmt=auto?w=1280&h=960'
	}] )
	
	const files2 = ref<UTSJSONObject[]>([])
	
	const files3 = ref<UTSJSONObject[]>([])
	
	const files4 = ref<UTSJSONObject[]>([])
	
	const files5 = ref<UTSJSONObject[]>([])
	
	const formData = ref<UTSJSONObject>({
		'bucket': "shaokx",
		'key': "/newhouse/20240718102240.png",
		'policy': "eyJjb25kaXRpb25zIjpbWyJlcSIsIiRidWNrZXQiLCJzaGFva3giXSxbImVxIiwiJGtleSIsIi9uZXdob3VzZS8yMDI0MDcxODEwMjI0MC5wbmciXSxbImVxIiwiJHgtYW16LW1ldGEtZGVzY3JpcHRpb24iLCLmlYjmnpzlm74iXSxbImVxIiwiJHgtYW16LWRhdGUiLCIyMDI0MDcxOFQwMjIyNDBaIl0sWyJlcSIsIiR4LWFtei1hbGdvcml0aG0iLCJBV1M0LUhNQUMtU0hBMjU2Il0sWyJlcSIsIiR4LWFtei1jcmVkZW50aWFsIiwiS3ZxMnZoU3VCODZTeU1RalBPTVkvMjAyNDA3MTgvdXMtZWFzdC0xL3MzL2F3czRfcmVxdWVzdCJdXSwiZXhwaXJhdGlvbiI6IjIwMjQtMDctMTlUMDI6MjI6MDAuMjIyWiJ9",
		'x-amz-algorithm': "AWS4-HMAC-SHA256",
		'x-amz-credential': "Kvq2vhSuB86SyMQjPOMY/20240718/us-east-1/s3/aws4_request",
		'x-amz-date': "20240718T022240Z",
		'x-amz-meta-description': "效果图",
		'x-amz-signature': "650b89ad802c2aab3b05536b30c02b4ac5116454421e9662c0b4d1a69069f4c7"
	})
	
	function change1(files: UxUploadFile[]) {
		console.log(files);
	}
	
	function change2(files: UxUploadFile[]) {
		console.log(files);
	}
	
	function change3(files: UxUploadFile[]) {
		console.log(files);
	}
	
	function change4(files: UxUploadFile[]) {
		console.log(files);
	}
	
	function change5(files: UxUploadFile[]) {
		console.log(files);
	}
	
	function error(err: string) {
		uni.showToast({
			title: err,
			icon: 'none'
		})
	}
	
	function beforeUpload(path: string): UTSJSONObject | null {
		return null
	}
	
	function afterUpload(data: string):string {
		uni.hideLoading()
		let res = JSON.parseObject(data)
		let d = res?.getJSON('data')
		return d?.getString('url') ?? ''
	}
	
	async function beforeDel(index: number, file: UxUploadFile):Promise<boolean> {
		return new Promise<boolean>((resolve) => {
			uni.showModal({
				content: '确定删除吗?',
				success: (e) => {
					if(e.confirm) {
						resolve(true)
					} else {
						resolve(false)
					}
				}
			})
		})
	}
	
	function onPreview(index: number, files: UxUploadFile[]) {
		let arr = files.filter((e):boolean => e.status == 'success').map((e): string => e.path)
		
		uni.previewImage({
			urls: arr,
			current: index
		})
		
		// 视频未处理
	}
	
	function submit() {
		uni.showLoading({
			title: '上传中...',
		})
		uxUploadRef.value?.$callMethod('upload')
	}
	
	const showDoc = ref(false)
	function onDoc() {
		plus.openWeb({
			title: '在线文档',
			url: 'https://www.uxframe.cn/component/upload.html',
			// blur: 1,
			success: () => {
				showDoc.value = true
			},
			complete: () => {
				showDoc.value = false
			}
		})
	}
	
	onLoad((e) => {
		title.value = e['title'] ?? ''
	})
	
</script><script setup>
	
	import * as plus from '@/uni_modules/ux-plus'
	import { UxUploadFile } from '@/uni_modules/ux-frame';
	
	const title = ref('')
	
	const uxUploadRef = ref<UxUploadComponentPublicInstance | null>(null)
	
	const url = 'https://test.api.fdproxy.cn/file/upload/add'
	
	const url2 = 'http://jxqft.com:9000/shaokx'
	
	const files1 = ref<UTSJSONObject[]>([{
		id: '1',
		url: 'http://gips0.baidu.com/it/u=1690853528,2506870245&fm=3028&app=3028&f=JPEG&fmt=auto?w=1024&h=1024'
	},{
		id: '2',
		url: 'http://gips2.baidu.com/it/u=195724436,3554684702&fm=3028&app=3028&f=JPEG&fmt=auto?w=1280&h=960'
	}] )
	
	const files2 = ref<UTSJSONObject[]>([])
	
	const files3 = ref<UTSJSONObject[]>([])
	
	const files4 = ref<UTSJSONObject[]>([])
	
	const files5 = ref<UTSJSONObject[]>([])
	
	const formData = ref<UTSJSONObject>({
		'bucket': "shaokx",
		'key': "/newhouse/20240718102240.png",
		'policy': "eyJjb25kaXRpb25zIjpbWyJlcSIsIiRidWNrZXQiLCJzaGFva3giXSxbImVxIiwiJGtleSIsIi9uZXdob3VzZS8yMDI0MDcxODEwMjI0MC5wbmciXSxbImVxIiwiJHgtYW16LW1ldGEtZGVzY3JpcHRpb24iLCLmlYjmnpzlm74iXSxbImVxIiwiJHgtYW16LWRhdGUiLCIyMDI0MDcxOFQwMjIyNDBaIl0sWyJlcSIsIiR4LWFtei1hbGdvcml0aG0iLCJBV1M0LUhNQUMtU0hBMjU2Il0sWyJlcSIsIiR4LWFtei1jcmVkZW50aWFsIiwiS3ZxMnZoU3VCODZTeU1RalBPTVkvMjAyNDA3MTgvdXMtZWFzdC0xL3MzL2F3czRfcmVxdWVzdCJdXSwiZXhwaXJhdGlvbiI6IjIwMjQtMDctMTlUMDI6MjI6MDAuMjIyWiJ9",
		'x-amz-algorithm': "AWS4-HMAC-SHA256",
		'x-amz-credential': "Kvq2vhSuB86SyMQjPOMY/20240718/us-east-1/s3/aws4_request",
		'x-amz-date': "20240718T022240Z",
		'x-amz-meta-description': "效果图",
		'x-amz-signature': "650b89ad802c2aab3b05536b30c02b4ac5116454421e9662c0b4d1a69069f4c7"
	})
	
	function change1(files: UxUploadFile[]) {
		console.log(files);
	}
	
	function change2(files: UxUploadFile[]) {
		console.log(files);
	}
	
	function change3(files: UxUploadFile[]) {
		console.log(files);
	}
	
	function change4(files: UxUploadFile[]) {
		console.log(files);
	}
	
	function change5(files: UxUploadFile[]) {
		console.log(files);
	}
	
	function error(err: string) {
		uni.showToast({
			title: err,
			icon: 'none'
		})
	}
	
	function beforeUpload(path: string): UTSJSONObject | null {
		return null
	}
	
	function afterUpload(data: string):string {
		uni.hideLoading()
		let res = JSON.parseObject(data)
		let d = res?.getJSON('data')
		return d?.getString('url') ?? ''
	}
	
	async function beforeDel(index: number, file: UxUploadFile):Promise<boolean> {
		return new Promise<boolean>((resolve) => {
			uni.showModal({
				content: '确定删除吗?',
				success: (e) => {
					if(e.confirm) {
						resolve(true)
					} else {
						resolve(false)
					}
				}
			})
		})
	}
	
	function onPreview(index: number, files: UxUploadFile[]) {
		let arr = files.filter((e):boolean => e.status == 'success').map((e): string => e.path)
		
		uni.previewImage({
			urls: arr,
			current: index
		})
		
		// 视频未处理
	}
	
	function submit() {
		uni.showLoading({
			title: '上传中...',
		})
		uxUploadRef.value?.$callMethod('upload')
	}
	
	const showDoc = ref(false)
	function onDoc() {
		plus.openWeb({
			title: '在线文档',
			url: 'https://www.uxframe.cn/component/upload.html',
			// blur: 1,
			success: () => {
				showDoc.value = true
			},
			complete: () => {
				showDoc.value = false
			}
		})
	}
	
	onLoad((e) => {
		title.value = e['title'] ?? ''
	})
	
</script>css
<style lang="scss">
	
</style><style lang="scss">
	
</style>