20260720172840
This commit is contained in:
1 parent
cda7f16d3a
commit
94207c77ff
3117 files changed
+201407
-1236
No files matched your search
@@ -0,0 +1,49 @@
|
||||
# _semantic
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { UploadOutlined } from '@antdv-next/icons'
|
||||
import { computed } from 'vue'
|
||||
import { SemanticPreview } from '@/components/semantic'
|
||||
import { useComponentLocale } from '@/composables/use-locale'
|
||||
import { locales } from '../locales'
|
||||
|
||||
const { t } = useComponentLocale(locales)
|
||||
|
||||
const semantics = computed(() => [
|
||||
{ name: 'root', desc: t('root'), version: '1.0.0' },
|
||||
{ name: 'list', desc: t('list'), version: '1.0.0' },
|
||||
{ name: 'item', desc: t('item'), version: '1.0.0' },
|
||||
])
|
||||
|
||||
const defaultFileList = [
|
||||
{ uid: '1', name: 'xxx.png', status: 'uploading', url: 'http://www.baidu.com/xxx.png', percent: 33 },
|
||||
{ uid: '2', name: 'yyy.png', status: 'done', url: 'http://www.baidu.com/yyy.png' },
|
||||
{ uid: '3', name: 'zzz.png', status: 'error', response: 'Server Error 500', url: 'http://www.baidu.com/zzz.png' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<SemanticPreview
|
||||
component-name="Upload"
|
||||
:semantics="semantics"
|
||||
>
|
||||
<template #default="{ classes }">
|
||||
<a-upload
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
:default-file-list="defaultFileList"
|
||||
:classes="classes"
|
||||
>
|
||||
<a-button>
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
Upload
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</template>
|
||||
</SemanticPreview>
|
||||
</template>
|
||||
```
|
||||
@@ -0,0 +1,118 @@
|
||||
# Avatar
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
Click to upload user's avatar, and validate size and format of picture with `beforeUpload`.
|
||||
|
||||
> The return value of function `beforeUpload` can be a Promise to check asynchronously. [demo](https://upload-react-component.vercel.app/demo/before-upload#beforeupload)
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { UploadEmits, UploadProps } from 'antdv-next'
|
||||
import { LoadingOutlined, PlusOutlined } from '@antdv-next/icons'
|
||||
import { message } from 'antdv-next'
|
||||
import { ref } from 'vue'
|
||||
|
||||
type FileType = Parameters<NonNullable<UploadProps['beforeUpload']>>[0]
|
||||
|
||||
const loading = ref(false)
|
||||
const imageUrl = ref('')
|
||||
|
||||
function getBase64(img: FileType) {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
const reader = new FileReader()
|
||||
reader.readAsDataURL(img)
|
||||
reader.onload = () => resolve(reader.result as string)
|
||||
reader.onerror = error => reject(error)
|
||||
})
|
||||
}
|
||||
|
||||
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
|
||||
const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png'
|
||||
if (!isJpgOrPng) {
|
||||
message.error('You can only upload JPG/PNG file!')
|
||||
}
|
||||
const isLt2M = file.size / 1024 / 1024 < 2
|
||||
if (!isLt2M) {
|
||||
message.error('Image must smaller than 2MB!')
|
||||
}
|
||||
return isJpgOrPng && isLt2M
|
||||
}
|
||||
|
||||
const handleChange: UploadEmits['change'] = async (info) => {
|
||||
if (info.file?.status === 'uploading') {
|
||||
loading.value = true
|
||||
return
|
||||
}
|
||||
if (info.file?.status === 'done') {
|
||||
try {
|
||||
if (info.file.originFileObj) {
|
||||
imageUrl.value = await getBase64(info.file.originFileObj as FileType)
|
||||
}
|
||||
}
|
||||
finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
else {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-flex gap="middle" wrap>
|
||||
<a-upload
|
||||
name="avatar"
|
||||
list-type="picture-card"
|
||||
class="avatar-uploader"
|
||||
:show-upload-list="false"
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
:before-upload="beforeUpload"
|
||||
@change="handleChange"
|
||||
>
|
||||
<img
|
||||
v-if="imageUrl"
|
||||
:src="imageUrl"
|
||||
alt="avatar"
|
||||
:draggable="false"
|
||||
style="width: 100%"
|
||||
>
|
||||
<button v-else style="border: 0; background: none" type="button">
|
||||
<LoadingOutlined v-if="loading" />
|
||||
<PlusOutlined v-else />
|
||||
<div style="margin-top: 8px">
|
||||
Upload
|
||||
</div>
|
||||
</button>
|
||||
</a-upload>
|
||||
|
||||
<a-upload
|
||||
name="avatar"
|
||||
list-type="picture-circle"
|
||||
class="avatar-uploader"
|
||||
:show-upload-list="false"
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
:before-upload="beforeUpload"
|
||||
@change="handleChange"
|
||||
>
|
||||
<img
|
||||
v-if="imageUrl"
|
||||
:src="imageUrl"
|
||||
alt="avatar"
|
||||
:draggable="false"
|
||||
style="width: 100%"
|
||||
>
|
||||
<button v-else style="border: 0; background: none" type="button">
|
||||
<LoadingOutlined v-if="loading" />
|
||||
<PlusOutlined v-else />
|
||||
<div style="margin-top: 8px">
|
||||
Upload
|
||||
</div>
|
||||
</button>
|
||||
</a-upload>
|
||||
</a-flex>
|
||||
</template>
|
||||
```
|
||||
@@ -0,0 +1,48 @@
|
||||
# Upload by clicking
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
Classic mode. File selection dialog pops up when upload button is clicked.
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { UploadEmits } from 'antdv-next'
|
||||
import { UploadOutlined } from '@antdv-next/icons'
|
||||
import { message } from 'antdv-next'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const fileList = ref([])
|
||||
const onChange: UploadEmits['change'] = (info) => {
|
||||
if (info.file?.status !== 'uploading') {
|
||||
console.log(info.file, info.fileList)
|
||||
}
|
||||
if (info.file?.status === 'done') {
|
||||
message.success(`${info.file.name} file uploaded successfully`)
|
||||
}
|
||||
else if (info.file?.status === 'error') {
|
||||
message.error(`${info.file.name} file upload failed.`)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-upload
|
||||
v-model:file-list="fileList"
|
||||
name="file"
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
:headers="{
|
||||
authorization: 'authorization-text',
|
||||
}"
|
||||
@change="onChange"
|
||||
>
|
||||
<a-button>
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
Click to Upload
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</template>
|
||||
```
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
# Component Token
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
Component Token Debug.
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { UploadEmits, UploadFile } from 'antdv-next'
|
||||
import { UploadOutlined } from '@antdv-next/icons'
|
||||
|
||||
const defaultFileList: UploadFile[] = [
|
||||
{
|
||||
uid: '1',
|
||||
name: 'xxx.png',
|
||||
status: 'uploading',
|
||||
url: 'http://www.baidu.com/xxx.png',
|
||||
percent: 33,
|
||||
},
|
||||
{
|
||||
uid: '2',
|
||||
name: 'yyy.png',
|
||||
status: 'done',
|
||||
url: 'http://www.baidu.com/yyy.png',
|
||||
},
|
||||
{
|
||||
uid: '3',
|
||||
name: 'zzz.png',
|
||||
status: 'error',
|
||||
response: 'Server Error 500',
|
||||
url: 'http://www.baidu.com/zzz.png',
|
||||
},
|
||||
]
|
||||
|
||||
const handleChange: UploadEmits['change'] = ({ file, fileList }) => {
|
||||
if (file.status !== 'uploading') {
|
||||
console.log(file, fileList)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-config-provider
|
||||
:theme="{
|
||||
components: {
|
||||
Upload: {
|
||||
actionsColor: 'yellow',
|
||||
},
|
||||
},
|
||||
}"
|
||||
>
|
||||
<a-upload
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
:default-file-list="defaultFileList"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-button>
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
Upload
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</a-config-provider>
|
||||
</template>
|
||||
```
|
||||
@@ -0,0 +1,105 @@
|
||||
# Crop image before uploading
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
Use [antd-img-crop](https://github.com/nanxiaobei/antd-img-crop) to crop image before uploading.
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { UploadEmits, UploadFile, UploadProps } from 'antdv-next'
|
||||
import { ref } from 'vue'
|
||||
|
||||
type FileType = Parameters<NonNullable<UploadProps['beforeUpload']>>[0]
|
||||
|
||||
const fileList = ref<UploadFile[]>([
|
||||
{
|
||||
uid: '-1',
|
||||
name: 'image.png',
|
||||
status: 'done',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
},
|
||||
])
|
||||
|
||||
function getBase64(file: FileType) {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
const reader = new FileReader()
|
||||
reader.readAsDataURL(file)
|
||||
reader.onload = () => resolve(reader.result as string)
|
||||
reader.onerror = error => reject(error)
|
||||
})
|
||||
}
|
||||
|
||||
function loadImage(src: string) {
|
||||
return new Promise<HTMLImageElement>((resolve, reject) => {
|
||||
const img = new Image()
|
||||
img.onload = () => resolve(img)
|
||||
img.onerror = reject
|
||||
img.src = src
|
||||
})
|
||||
}
|
||||
|
||||
async function cropToSquare(file: FileType) {
|
||||
if (!file.type.startsWith('image/')) {
|
||||
return file
|
||||
}
|
||||
const dataUrl = await getBase64(file)
|
||||
const img = await loadImage(dataUrl)
|
||||
const size = Math.min(img.width, img.height)
|
||||
const canvas = document.createElement('canvas')
|
||||
canvas.width = size
|
||||
canvas.height = size
|
||||
const ctx = canvas.getContext('2d')
|
||||
if (!ctx) {
|
||||
return file
|
||||
}
|
||||
const startX = (img.width - size) / 2
|
||||
const startY = (img.height - size) / 2
|
||||
ctx.drawImage(img, startX, startY, size, size, 0, 0, size, size)
|
||||
return new Promise<File>((resolve) => {
|
||||
canvas.toBlob((blob) => {
|
||||
if (!blob) {
|
||||
resolve(file as File)
|
||||
return
|
||||
}
|
||||
resolve(new File([blob], file.name, { type: file.type || 'image/png' }))
|
||||
}, file.type || 'image/png')
|
||||
})
|
||||
}
|
||||
|
||||
const beforeUpload: UploadProps['beforeUpload'] = async (file) => {
|
||||
return cropToSquare(file)
|
||||
}
|
||||
|
||||
const handleChange: UploadEmits['change'] = ({ fileList: newFileList }) => {
|
||||
fileList.value = newFileList
|
||||
}
|
||||
|
||||
async function handlePreview(file: UploadFile) {
|
||||
let src = file.url as string
|
||||
if (!src && file.originFileObj) {
|
||||
src = await getBase64(file.originFileObj as FileType)
|
||||
}
|
||||
const image = new Image()
|
||||
image.src = src
|
||||
const imgWindow = window.open(src)
|
||||
imgWindow?.document.write(image.outerHTML)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-upload
|
||||
v-model:file-list="fileList"
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
list-type="picture-card"
|
||||
:before-upload="beforeUpload"
|
||||
:on-preview="handlePreview"
|
||||
@change="handleChange"
|
||||
>
|
||||
<template v-if="fileList.length < 5">
|
||||
+ Upload
|
||||
</template>
|
||||
</a-upload>
|
||||
</template>
|
||||
```
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
# Customize Progress Bar
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
Use `progress` for customize progress bar.
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { UploadEmits } from 'antdv-next'
|
||||
import { UploadOutlined } from '@antdv-next/icons'
|
||||
import { message } from 'antdv-next'
|
||||
|
||||
const handleChange: UploadEmits['change'] = (info) => {
|
||||
if (info.file?.status !== 'uploading') {
|
||||
console.log(info.file, info.fileList)
|
||||
}
|
||||
if (info.file?.status === 'done') {
|
||||
message.success(`${info.file.name} file uploaded successfully`)
|
||||
}
|
||||
else if (info.file?.status === 'error') {
|
||||
message.error(`${info.file.name} file upload failed.`)
|
||||
}
|
||||
}
|
||||
|
||||
function formatPercent(percent?: number) {
|
||||
return percent && `${Number.parseFloat(percent.toFixed(2))}%`
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-upload
|
||||
name="file"
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
:headers="{
|
||||
authorization: 'authorization-text',
|
||||
}"
|
||||
:progress="{
|
||||
strokeColor: {
|
||||
'0%': '#108ee9',
|
||||
'100%': '#87d068',
|
||||
},
|
||||
size: 3,
|
||||
format: formatPercent,
|
||||
}"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-button>
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
Click to Upload
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</template>
|
||||
```
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
# Default Files
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
Use `defaultFileList` for uploaded files when page init.
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { UploadEmits, UploadFile } from 'antdv-next'
|
||||
import { UploadOutlined } from '@antdv-next/icons'
|
||||
|
||||
const defaultFileList: UploadFile[] = [
|
||||
{
|
||||
uid: '1',
|
||||
name: 'xxx.png',
|
||||
status: 'uploading',
|
||||
url: 'http://www.baidu.com/xxx.png',
|
||||
percent: 33,
|
||||
},
|
||||
{
|
||||
uid: '2',
|
||||
name: 'yyy.png',
|
||||
status: 'done',
|
||||
url: 'http://www.baidu.com/yyy.png',
|
||||
},
|
||||
{
|
||||
uid: '3',
|
||||
name: 'zzz.png',
|
||||
status: 'error',
|
||||
response: 'Server Error 500',
|
||||
url: 'http://www.baidu.com/zzz.png',
|
||||
},
|
||||
]
|
||||
|
||||
const handleChange: UploadEmits['change'] = ({ file, fileList }) => {
|
||||
if (file?.status !== 'uploading') {
|
||||
console.log(file, fileList)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-upload
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
:default-file-list="defaultFileList"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-button>
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
Upload
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</template>
|
||||
```
|
||||
@@ -0,0 +1,24 @@
|
||||
# Upload directory
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
You can select and upload a whole directory. [Can still select files when uploading a folder in Safari?](#can-still-select-files-when-uploading-a-folder-in-safari)
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { UploadOutlined } from '@antdv-next/icons'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-upload action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload" directory>
|
||||
<a-button>
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
Upload Directory
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</template>
|
||||
```
|
||||
@@ -0,0 +1,122 @@
|
||||
# Drag sorting of uploadList
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
By using `itemRender`, we can integrate upload with drag to implement drag sorting of uploadList.
|
||||
|
||||
```css
|
||||
.is-dragging a {
|
||||
pointer-events: none;
|
||||
}
|
||||
```
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { UploadEmits, UploadFile } from 'antdv-next'
|
||||
import { UploadOutlined } from '@antdv-next/icons'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const fileList = ref<UploadFile[]>([
|
||||
{
|
||||
uid: '-1',
|
||||
name: 'image1.png',
|
||||
status: 'done',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
},
|
||||
{
|
||||
uid: '-2',
|
||||
name: 'image2.png',
|
||||
status: 'done',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
},
|
||||
{
|
||||
uid: '-3',
|
||||
name: 'image3.png',
|
||||
status: 'done',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
},
|
||||
{
|
||||
uid: '-4',
|
||||
name: 'image4.png',
|
||||
status: 'done',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
},
|
||||
{
|
||||
uid: '-5',
|
||||
name: 'image.png',
|
||||
status: 'error',
|
||||
},
|
||||
])
|
||||
|
||||
const draggingUid = ref<string | null>(null)
|
||||
|
||||
const handleChange: UploadEmits['change'] = ({ fileList: newFileList }) => {
|
||||
fileList.value = newFileList
|
||||
}
|
||||
|
||||
function handleDragStart(uid: string, event: DragEvent) {
|
||||
draggingUid.value = uid
|
||||
event.dataTransfer?.setData('text/plain', uid)
|
||||
}
|
||||
|
||||
function handleDragEnd() {
|
||||
draggingUid.value = null
|
||||
}
|
||||
|
||||
function handleDrop(overUid: string, event: DragEvent) {
|
||||
const activeUid = event.dataTransfer?.getData('text/plain')
|
||||
if (!activeUid || activeUid === overUid) {
|
||||
return
|
||||
}
|
||||
const activeIndex = fileList.value.findIndex(file => file.uid === activeUid)
|
||||
const overIndex = fileList.value.findIndex(file => file.uid === overUid)
|
||||
if (activeIndex < 0 || overIndex < 0) {
|
||||
return
|
||||
}
|
||||
const nextList = fileList.value.slice()
|
||||
const [moved] = nextList.splice(activeIndex, 1)
|
||||
nextList.splice(overIndex, 0, moved)
|
||||
fileList.value = nextList
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-upload
|
||||
v-model:file-list="fileList"
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
@change="handleChange"
|
||||
>
|
||||
<template #itemRender="{ originNode, file }">
|
||||
<div
|
||||
class="upload-sort-item"
|
||||
:class="{ 'is-dragging': draggingUid === file.uid }"
|
||||
draggable="true"
|
||||
@dragstart="(event) => handleDragStart(file.uid, event)"
|
||||
@dragover.prevent
|
||||
@drop="(event) => handleDrop(file.uid, event)"
|
||||
@dragend="handleDragEnd"
|
||||
>
|
||||
<component :is="originNode" />
|
||||
</div>
|
||||
</template>
|
||||
<a-button>
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
Click to Upload
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.upload-sort-item {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.is-dragging a {
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
@@ -0,0 +1,55 @@
|
||||
# Drag and Drop
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
You can drag files to a specific area, to upload. Alternatively, you can also upload by selecting.
|
||||
|
||||
We can upload several files at once in modern browsers by giving the input the `multiple` attribute.
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { UploadEmits } from 'antdv-next'
|
||||
import { InboxOutlined } from '@antdv-next/icons'
|
||||
import { message } from 'antdv-next'
|
||||
|
||||
const handleChange: UploadEmits['change'] = (info) => {
|
||||
const { status } = info.file
|
||||
if (status !== 'uploading') {
|
||||
console.log(info.file, info.fileList)
|
||||
}
|
||||
if (status === 'done') {
|
||||
message.success(`${info.file.name} file uploaded successfully.`)
|
||||
}
|
||||
else if (status === 'error') {
|
||||
message.error(`${info.file.name} file upload failed.`)
|
||||
}
|
||||
}
|
||||
|
||||
const handleDrop: UploadEmits['drop'] = (event) => {
|
||||
console.log('Dropped files', event.dataTransfer?.files)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-upload-dragger
|
||||
name="file"
|
||||
multiple
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
@change="handleChange"
|
||||
@drop="handleDrop"
|
||||
>
|
||||
<p class="ant-upload-drag-icon">
|
||||
<InboxOutlined />
|
||||
</p>
|
||||
<p class="ant-upload-text">
|
||||
Click or drag file to this area to upload
|
||||
</p>
|
||||
<p class="ant-upload-hint">
|
||||
Support for a single or bulk upload. Strictly prohibited from uploading company data or other
|
||||
banned files.
|
||||
</p>
|
||||
</a-upload-dragger>
|
||||
</template>
|
||||
```
|
||||
@@ -0,0 +1,146 @@
|
||||
# Custom show icon
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
Displays the corresponding by default by type icon
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { UploadEmits, UploadFile, UploadProps } from 'antdv-next'
|
||||
import {
|
||||
FileExcelTwoTone,
|
||||
FilePdfTwoTone,
|
||||
FileWordTwoTone,
|
||||
LoadingOutlined,
|
||||
PaperClipOutlined,
|
||||
PictureTwoTone,
|
||||
PlusOutlined,
|
||||
} from '@antdv-next/icons'
|
||||
import { h, ref } from 'vue'
|
||||
|
||||
type FileType = Parameters<NonNullable<UploadProps['beforeUpload']>>[0]
|
||||
|
||||
const previewOpen = ref(false)
|
||||
const previewImage = ref('')
|
||||
const fileList = ref<UploadFile[]>([
|
||||
{
|
||||
uid: '-2',
|
||||
name: 'pdf.pdf',
|
||||
status: 'done',
|
||||
url: 'http://cdn07.foxitsoftware.cn/pub/foxit/cpdf/FoxitCompanyProfile.pdf',
|
||||
},
|
||||
{
|
||||
uid: '-3',
|
||||
name: 'doc.doc',
|
||||
status: 'done',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.doc',
|
||||
},
|
||||
{
|
||||
uid: '-4',
|
||||
name: 'image.png',
|
||||
status: 'error',
|
||||
},
|
||||
{
|
||||
uid: '-5',
|
||||
name: 'pdf.pdf',
|
||||
status: 'error',
|
||||
},
|
||||
{
|
||||
uid: '-6',
|
||||
name: 'doc.doc',
|
||||
status: 'error',
|
||||
},
|
||||
])
|
||||
|
||||
function getBase64(file: FileType) {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
const reader = new FileReader()
|
||||
reader.readAsDataURL(file)
|
||||
reader.onload = () => resolve(reader.result as string)
|
||||
reader.onerror = error => reject(error)
|
||||
})
|
||||
}
|
||||
|
||||
async function handlePreview(file: UploadFile) {
|
||||
if (!file.url && !file.preview && file.originFileObj) {
|
||||
file.preview = await getBase64(file.originFileObj as FileType)
|
||||
}
|
||||
previewOpen.value = true
|
||||
previewImage.value = (file.url || (file.preview as string)) ?? ''
|
||||
}
|
||||
|
||||
const handleChange: UploadEmits['change'] = ({ fileList: newFileList }) => {
|
||||
fileList.value = newFileList
|
||||
}
|
||||
|
||||
function handlePreviewOpenChange(visible: boolean) {
|
||||
previewOpen.value = visible
|
||||
}
|
||||
|
||||
function handleAfterOpenChange(visible: boolean) {
|
||||
if (!visible) {
|
||||
previewImage.value = ''
|
||||
}
|
||||
}
|
||||
|
||||
const fileSufIconList = [
|
||||
{ icon: FilePdfTwoTone, suf: ['.pdf'] },
|
||||
{ icon: FileExcelTwoTone, suf: ['.xlsx', '.xls', '.csv'] },
|
||||
{ icon: FileWordTwoTone, suf: ['.doc', '.docx'] },
|
||||
{
|
||||
icon: PictureTwoTone,
|
||||
suf: ['.webp', '.svg', '.png', '.gif', '.jpg', '.jpeg', '.jfif', '.bmp', '.dpg'],
|
||||
},
|
||||
]
|
||||
|
||||
const iconRender: UploadProps['iconRender'] = (file, listType) => {
|
||||
let icon = file.status === 'uploading' ? h(LoadingOutlined) : h(PaperClipOutlined)
|
||||
if (listType === 'picture' || listType === 'picture-card' || listType === 'picture-circle') {
|
||||
if (listType === 'picture-card' && file.status === 'uploading') {
|
||||
icon = h(LoadingOutlined)
|
||||
}
|
||||
else {
|
||||
const suffix = file.name.slice(file.name.lastIndexOf('.'))
|
||||
fileSufIconList.forEach((item) => {
|
||||
if (item.suf.includes(suffix)) {
|
||||
icon = h(item.icon)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
return icon
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-upload
|
||||
v-model:file-list="fileList"
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
list-type="picture-card"
|
||||
:on-preview="handlePreview"
|
||||
:icon-render="iconRender"
|
||||
@change="handleChange"
|
||||
>
|
||||
<template v-if="fileList.length < 8">
|
||||
<button style="border: 0; background: none" type="button">
|
||||
<PlusOutlined />
|
||||
<div style="margin-top: 8px">
|
||||
Upload
|
||||
</div>
|
||||
</button>
|
||||
</template>
|
||||
</a-upload>
|
||||
<a-image
|
||||
v-if="previewImage"
|
||||
:styles="{ root: { display: 'none' } }"
|
||||
:preview="{
|
||||
open: previewOpen,
|
||||
onOpenChange: handlePreviewOpenChange,
|
||||
afterOpenChange: handleAfterOpenChange,
|
||||
}"
|
||||
:src="previewImage"
|
||||
/>
|
||||
</template>
|
||||
```
|
||||
@@ -0,0 +1,59 @@
|
||||
# Complete control over file list
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
You can gain full control over filelist by configuring `fileList`. You can accomplish all kinds of customized functions. The following shows two circumstances:
|
||||
|
||||
1. limit the number of uploaded files.
|
||||
|
||||
2. read from response and show file link.
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { UploadEmits, UploadFile } from 'antdv-next'
|
||||
import { UploadOutlined } from '@antdv-next/icons'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const fileList = ref<UploadFile[]>([
|
||||
{
|
||||
uid: '-1',
|
||||
name: 'xxx.png',
|
||||
status: 'done',
|
||||
url: 'http://www.baidu.com/xxx.png',
|
||||
},
|
||||
])
|
||||
|
||||
const handleChange: UploadEmits['change'] = (info) => {
|
||||
let newFileList = [...info.fileList]
|
||||
|
||||
newFileList = newFileList.slice(-2)
|
||||
|
||||
newFileList = newFileList.map((file) => {
|
||||
if (file.response && typeof file.response === 'object' && 'url' in file.response) {
|
||||
file.url = (file.response as { url?: string }).url
|
||||
}
|
||||
return file
|
||||
})
|
||||
|
||||
fileList.value = newFileList
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-upload
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
multiple
|
||||
:file-list="fileList"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-button>
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
Upload
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</template>
|
||||
```
|
||||
@@ -0,0 +1,43 @@
|
||||
# Max Count
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
Limit files with `maxCount`. Will replace current one when `maxCount` is `1`.
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { UploadOutlined } from '@antdv-next/icons'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-space direction="vertical" style="width: 100%" size="large">
|
||||
<a-upload
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
list-type="picture"
|
||||
:max-count="1"
|
||||
>
|
||||
<a-button>
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
Upload (Max: 1)
|
||||
</a-button>
|
||||
</a-upload>
|
||||
<a-upload
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
list-type="picture"
|
||||
:max-count="3"
|
||||
multiple
|
||||
>
|
||||
<a-button>
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
Upload (Max: 3)
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</a-space>
|
||||
</template>
|
||||
```
|
||||
@@ -0,0 +1,46 @@
|
||||
# Paste
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
Copy the file and paste it anywhere on the page to upload.
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { UploadEmits } from 'antdv-next'
|
||||
import { UploadOutlined } from '@antdv-next/icons'
|
||||
import { message } from 'antdv-next'
|
||||
|
||||
const handleChange: UploadEmits['change'] = (info) => {
|
||||
if (info.file?.status !== 'uploading') {
|
||||
console.log(info.file, info.fileList)
|
||||
}
|
||||
if (info.file?.status === 'done') {
|
||||
message.success(`${info.file.name} file uploaded successfully`)
|
||||
}
|
||||
else if (info.file?.status === 'error') {
|
||||
message.error(`${info.file.name} file upload failed.`)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-upload
|
||||
name="file"
|
||||
pastable
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
:headers="{
|
||||
authorization: 'authorization-text',
|
||||
}"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-button>
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
Paste or click to upload
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</template>
|
||||
```
|
||||
@@ -0,0 +1,118 @@
|
||||
# Pictures Wall
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
After users upload picture, the thumbnail will be shown in list. The upload button will disappear when count meets limitation.
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { UploadEmits, UploadFile, UploadProps } from 'antdv-next'
|
||||
import { PlusOutlined } from '@antdv-next/icons'
|
||||
import { ref } from 'vue'
|
||||
|
||||
type FileType = Parameters<NonNullable<UploadProps['beforeUpload']>>[0]
|
||||
|
||||
const previewOpen = ref(false)
|
||||
const previewImage = ref('')
|
||||
const fileList = ref<UploadFile[]>([
|
||||
{
|
||||
uid: '-1',
|
||||
name: 'image.png',
|
||||
status: 'done',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
},
|
||||
{
|
||||
uid: '-2',
|
||||
name: 'image.png',
|
||||
status: 'done',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
},
|
||||
{
|
||||
uid: '-3',
|
||||
name: 'image.png',
|
||||
status: 'done',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
},
|
||||
{
|
||||
uid: '-4',
|
||||
name: 'image.png',
|
||||
status: 'done',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
},
|
||||
{
|
||||
uid: '-xxx',
|
||||
percent: 50,
|
||||
name: 'image.png',
|
||||
status: 'uploading',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
},
|
||||
{
|
||||
uid: '-5',
|
||||
name: 'image.png',
|
||||
status: 'error',
|
||||
},
|
||||
])
|
||||
|
||||
function getBase64(file: FileType) {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
const reader = new FileReader()
|
||||
reader.readAsDataURL(file)
|
||||
reader.onload = () => resolve(reader.result as string)
|
||||
reader.onerror = error => reject(error)
|
||||
})
|
||||
}
|
||||
|
||||
async function handlePreview(file: UploadFile) {
|
||||
if (!file.url && !file.preview && file.originFileObj) {
|
||||
file.preview = await getBase64(file.originFileObj as FileType)
|
||||
}
|
||||
previewImage.value = (file.url || (file.preview as string)) ?? ''
|
||||
previewOpen.value = true
|
||||
}
|
||||
|
||||
const handleChange: UploadEmits['change'] = ({ fileList: newFileList }) => {
|
||||
fileList.value = newFileList
|
||||
}
|
||||
|
||||
function handlePreviewOpenChange(visible: boolean) {
|
||||
previewOpen.value = visible
|
||||
}
|
||||
|
||||
function handleAfterOpenChange(visible: boolean) {
|
||||
if (!visible) {
|
||||
previewImage.value = ''
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-upload
|
||||
v-model:file-list="fileList"
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
list-type="picture-card"
|
||||
@preview="handlePreview"
|
||||
@change="handleChange"
|
||||
>
|
||||
<template v-if="fileList.length < 8">
|
||||
<button style="border: 0; background: none" type="button">
|
||||
<PlusOutlined />
|
||||
<div style="margin-top: 8px">
|
||||
Upload
|
||||
</div>
|
||||
</button>
|
||||
</template>
|
||||
</a-upload>
|
||||
<a-image
|
||||
v-if="previewImage"
|
||||
:styles="{ root: { display: 'none' } }"
|
||||
:preview="{
|
||||
open: previewOpen,
|
||||
onOpenChange: handlePreviewOpenChange,
|
||||
afterOpenChange: handleAfterOpenChange,
|
||||
}"
|
||||
:src="previewImage"
|
||||
/>
|
||||
</template>
|
||||
```
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
# Pictures with picture-circle type
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
Alternative display for picture-card.
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { UploadEmits, UploadFile, UploadProps } from 'antdv-next'
|
||||
import { PlusOutlined } from '@antdv-next/icons'
|
||||
import { ref } from 'vue'
|
||||
|
||||
type FileType = Parameters<NonNullable<UploadProps['beforeUpload']>>[0]
|
||||
|
||||
const previewOpen = ref(false)
|
||||
const previewImage = ref('')
|
||||
const fileList = ref<UploadFile[]>([
|
||||
{
|
||||
uid: '-1',
|
||||
name: 'image.png',
|
||||
status: 'done',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
},
|
||||
{
|
||||
uid: '-xxx',
|
||||
percent: 50,
|
||||
name: 'image.png',
|
||||
status: 'uploading',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
},
|
||||
{
|
||||
uid: '-5',
|
||||
name: 'image.png',
|
||||
status: 'error',
|
||||
},
|
||||
])
|
||||
|
||||
function getBase64(file: FileType) {
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
const reader = new FileReader()
|
||||
reader.readAsDataURL(file)
|
||||
reader.onload = () => resolve(reader.result as string)
|
||||
reader.onerror = error => reject(error)
|
||||
})
|
||||
}
|
||||
|
||||
async function handlePreview(file: UploadFile) {
|
||||
console.log('file', file)
|
||||
if (!file.url && !file.preview && file.originFileObj) {
|
||||
file.preview = await getBase64(file.originFileObj as FileType)
|
||||
}
|
||||
previewImage.value = (file.url || (file.preview as string)) ?? ''
|
||||
previewOpen.value = true
|
||||
}
|
||||
|
||||
const handleChange: UploadEmits['change'] = ({ fileList: newFileList }) => {
|
||||
fileList.value = newFileList
|
||||
}
|
||||
|
||||
function handlePreviewOpenChange(visible: boolean) {
|
||||
previewOpen.value = visible
|
||||
}
|
||||
|
||||
function handleAfterOpenChange(visible: boolean) {
|
||||
if (!visible) {
|
||||
previewImage.value = ''
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-upload
|
||||
v-model:file-list="fileList"
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
list-type="picture-circle"
|
||||
@preview="handlePreview"
|
||||
@change="handleChange"
|
||||
>
|
||||
<template v-if="fileList.length < 8">
|
||||
<button style="border: 0; background: none" type="button">
|
||||
<PlusOutlined />
|
||||
<div style="margin-top: 8px">
|
||||
Upload
|
||||
</div>
|
||||
</button>
|
||||
</template>
|
||||
</a-upload>
|
||||
<a-image
|
||||
v-if="previewImage"
|
||||
:styles="{ root: { display: 'none' } }"
|
||||
:preview="{
|
||||
open: previewOpen,
|
||||
onOpenChange: handlePreviewOpenChange,
|
||||
afterOpenChange: handleAfterOpenChange,
|
||||
}"
|
||||
:src="previewImage"
|
||||
/>
|
||||
</template>
|
||||
```
|
||||
@@ -0,0 +1,50 @@
|
||||
# Pictures with list style
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
If uploaded file is a picture, the thumbnail can be shown. `IE8/9` do not support local thumbnail show. Please use `thumbUrl` instead.
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { UploadFile } from 'antdv-next'
|
||||
import { UploadOutlined } from '@antdv-next/icons'
|
||||
|
||||
const defaultFileList: UploadFile[] = [
|
||||
{
|
||||
uid: '0',
|
||||
name: 'xxx.png',
|
||||
status: 'uploading',
|
||||
percent: 33,
|
||||
},
|
||||
{
|
||||
uid: '-1',
|
||||
name: 'yyy.png',
|
||||
status: 'done',
|
||||
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
thumbUrl: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
||||
},
|
||||
{
|
||||
uid: '-2',
|
||||
name: 'zzz.png',
|
||||
status: 'error',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-upload
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
list-type="picture"
|
||||
:default-file-list="defaultFileList"
|
||||
>
|
||||
<a-button type="primary">
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
Upload
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</template>
|
||||
```
|
||||
@@ -0,0 +1,39 @@
|
||||
# Customize preview file
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
Customize local preview. Can handle with non-image format files such as video.
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { UploadProps } from 'antdv-next'
|
||||
import { UploadOutlined } from '@antdv-next/icons'
|
||||
|
||||
const previewFile: UploadProps['previewFile'] = (file) => {
|
||||
console.log('Your upload file:', file)
|
||||
return fetch('https://next.json-generator.com/api/json/get/4ytyBoLK8', {
|
||||
method: 'POST',
|
||||
body: file as BodyInit,
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(({ thumbnail }) => thumbnail)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-upload
|
||||
action="//jsonplaceholder.typicode.com/posts/"
|
||||
list-type="picture"
|
||||
:preview-file="previewFile"
|
||||
>
|
||||
<a-button>
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
Upload
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</template>
|
||||
```
|
||||
@@ -0,0 +1,110 @@
|
||||
# Custom semantic dom styling
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
You can customize the [semantic dom](#semantic-upload) style of Upload components by passing objects/functions through `classes` and `styles`.
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { UploadEmits, UploadFile, UploadProps } from 'antdv-next'
|
||||
import { UploadOutlined } from '@antdv-next/icons'
|
||||
|
||||
const classes: UploadProps['classes'] = {
|
||||
root: 'upload-demo-root',
|
||||
}
|
||||
|
||||
const stylesObject: UploadProps['styles'] = {
|
||||
item: {
|
||||
borderRadius: 2,
|
||||
backgroundColor: 'rgba(5, 5, 5, 0.06)',
|
||||
height: '30px',
|
||||
},
|
||||
}
|
||||
|
||||
const stylesFn: UploadProps['styles'] = (info) => {
|
||||
if (info.props.multiple) {
|
||||
return {
|
||||
root: { border: '1px solid #5459AC' },
|
||||
item: {
|
||||
borderRadius: 2,
|
||||
backgroundColor: 'rgba(5, 5, 5, 0.06)',
|
||||
height: '30px',
|
||||
},
|
||||
}
|
||||
}
|
||||
return {}
|
||||
}
|
||||
|
||||
const defaultFileList: UploadFile[] = [
|
||||
{
|
||||
uid: '1',
|
||||
name: 'xxx.png',
|
||||
status: 'uploading',
|
||||
url: 'http://www.baidu.com/xxx.png',
|
||||
percent: 33,
|
||||
},
|
||||
{
|
||||
uid: '2',
|
||||
name: 'yyy.png',
|
||||
status: 'done',
|
||||
url: 'http://www.baidu.com/yyy.png',
|
||||
},
|
||||
{
|
||||
uid: '3',
|
||||
name: 'zzz.png',
|
||||
status: 'error',
|
||||
response: 'Server Error 500',
|
||||
url: 'http://www.baidu.com/zzz.png',
|
||||
},
|
||||
]
|
||||
|
||||
const handleChange: UploadEmits['change'] = ({ file, fileList }) => {
|
||||
if (file?.status !== 'uploading') {
|
||||
console.log(file, fileList)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-flex gap="large" vertical>
|
||||
<a-upload
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
:classes="classes"
|
||||
:default-file-list="defaultFileList"
|
||||
:styles="stylesObject"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-button>
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
Upload
|
||||
</a-button>
|
||||
</a-upload>
|
||||
<a-upload
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
:classes="classes"
|
||||
:default-file-list="defaultFileList"
|
||||
:styles="stylesFn"
|
||||
multiple
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-button>
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
Upload
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</a-flex>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.upload-demo-root {
|
||||
border-radius: 6px;
|
||||
padding: 12px;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
# Transform file before request
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
Use `beforeUpload` for transform file before request such as add a watermark.
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { UploadProps } from 'antdv-next'
|
||||
import { UploadOutlined } from '@antdv-next/icons'
|
||||
|
||||
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
|
||||
return new Promise((resolve) => {
|
||||
const reader = new FileReader()
|
||||
reader.readAsDataURL(file)
|
||||
reader.onload = () => {
|
||||
const img = document.createElement('img')
|
||||
img.src = reader.result as string
|
||||
img.onload = () => {
|
||||
const canvas = document.createElement('canvas')
|
||||
canvas.width = img.naturalWidth
|
||||
canvas.height = img.naturalHeight
|
||||
const ctx = canvas.getContext('2d')
|
||||
if (!ctx) {
|
||||
resolve(file)
|
||||
return
|
||||
}
|
||||
ctx.drawImage(img, 0, 0)
|
||||
ctx.fillStyle = 'red'
|
||||
ctx.textBaseline = 'middle'
|
||||
ctx.font = '33px Arial'
|
||||
ctx.fillText('Antdv Next', 20, 20)
|
||||
canvas.toBlob((result) => {
|
||||
if (result) {
|
||||
resolve(result)
|
||||
}
|
||||
else {
|
||||
resolve(file)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-upload
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
list-type="picture"
|
||||
:before-upload="beforeUpload"
|
||||
>
|
||||
<a-button>
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
Upload
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</template>
|
||||
```
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
# Custom action icon and extra info
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
Use `showUploadList` for custom action icons and extra information of files.
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { UploadEmits, UploadFile, UploadProps } from 'antdv-next'
|
||||
import { StarOutlined, UploadOutlined } from '@antdv-next/icons'
|
||||
import { h } from 'vue'
|
||||
|
||||
const defaultFileList: UploadFile[] = [
|
||||
{
|
||||
uid: '1',
|
||||
name: 'xxx.png',
|
||||
size: 1234567,
|
||||
status: 'done',
|
||||
response: 'Server Error 500',
|
||||
url: 'http://www.baidu.com/xxx.png',
|
||||
},
|
||||
{
|
||||
uid: '2',
|
||||
name: 'yyy.png',
|
||||
size: 1234567,
|
||||
status: 'done',
|
||||
url: 'http://www.baidu.com/yyy.png',
|
||||
},
|
||||
{
|
||||
uid: '3',
|
||||
name: 'zzz.png',
|
||||
size: 1234567,
|
||||
status: 'error',
|
||||
response: 'Server Error 500',
|
||||
url: 'http://www.baidu.com/zzz.png',
|
||||
},
|
||||
]
|
||||
|
||||
const handleChange: UploadEmits['change'] = ({ file, fileList }) => {
|
||||
if (file?.status !== 'uploading') {
|
||||
console.log(file, fileList)
|
||||
}
|
||||
}
|
||||
|
||||
const showUploadList: UploadProps['showUploadList'] = {
|
||||
extra: ({ size = 0 }) => {
|
||||
return h('span', { style: { color: '#cccccc' } }, `(${(size / 1024 / 1024).toFixed(2)}MB)`)
|
||||
},
|
||||
showDownloadIcon: true,
|
||||
downloadIcon: 'Download',
|
||||
showRemoveIcon: true,
|
||||
removeIcon: h(StarOutlined, {
|
||||
onClick: (event: MouseEvent) => console.log(event, 'custom removeIcon event'),
|
||||
}),
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-upload
|
||||
action="https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload"
|
||||
:default-file-list="defaultFileList"
|
||||
:show-upload-list="showUploadList"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-button>
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
Upload
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</template>
|
||||
```
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
# Upload manually
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
Upload files manually after `beforeUpload` returns `false`.
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { UploadFile, UploadProps } from 'antdv-next'
|
||||
import { UploadOutlined } from '@antdv-next/icons'
|
||||
import { message } from 'antdv-next'
|
||||
import { ref } from 'vue'
|
||||
|
||||
const fileList = ref<UploadFile[]>([])
|
||||
const uploading = ref(false)
|
||||
|
||||
function handleUpload() {
|
||||
const formData = new FormData()
|
||||
fileList.value.forEach((file) => {
|
||||
formData.append('files[]', file as File)
|
||||
})
|
||||
uploading.value = true
|
||||
fetch('https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(() => {
|
||||
fileList.value = []
|
||||
message.success('upload successfully.')
|
||||
})
|
||||
.catch(() => {
|
||||
message.error('upload failed.')
|
||||
})
|
||||
.finally(() => {
|
||||
uploading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
const handleRemove: UploadProps['onRemove'] = (file) => {
|
||||
fileList.value = fileList.value.filter(item => item.uid !== file.uid)
|
||||
}
|
||||
|
||||
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
|
||||
fileList.value = [...fileList.value, file]
|
||||
return false
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-upload
|
||||
:before-upload="beforeUpload"
|
||||
:on-remove="handleRemove"
|
||||
:file-list="fileList"
|
||||
>
|
||||
<a-button>
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
Select File
|
||||
</a-button>
|
||||
</a-upload>
|
||||
<a-button
|
||||
type="primary"
|
||||
:disabled="fileList.length === 0"
|
||||
:loading="uploading"
|
||||
style="margin-top: 16px"
|
||||
@click="handleUpload"
|
||||
>
|
||||
{{ uploading ? 'Uploading' : 'Start Upload' }}
|
||||
</a-button>
|
||||
</template>
|
||||
```
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
# Upload png file only
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
`beforeUpload` only prevent upload behavior when return false or reject promise, the prevented file would still show in file list. Here is the example you can keep prevented files out of list by return `UPLOAD.LIST_IGNORE`.
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { UploadEmits, UploadProps } from 'antdv-next'
|
||||
import { UploadOutlined } from '@antdv-next/icons'
|
||||
import { message, Upload } from 'antdv-next'
|
||||
|
||||
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
|
||||
const isPng = file.type === 'image/png'
|
||||
if (!isPng) {
|
||||
message.error(`${file.name} is not a png file`)
|
||||
}
|
||||
return isPng || Upload.LIST_IGNORE
|
||||
}
|
||||
|
||||
const handleChange: UploadEmits['change'] = (info) => {
|
||||
console.log(info.fileList)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-upload :before-upload="beforeUpload" @change="handleChange">
|
||||
<a-button>
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
Upload png only
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</template>
|
||||
```
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
# Aliyun OSS
|
||||
|
||||
## Description (en-US)
|
||||
|
||||
Use Aliyun OSS upload example.
|
||||
|
||||
## Source
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import type { UploadEmits, UploadFile, UploadProps } from 'antdv-next'
|
||||
import { UploadOutlined } from '@antdv-next/icons'
|
||||
import { message } from 'antdv-next'
|
||||
import { onMounted, ref } from 'vue'
|
||||
|
||||
interface OSSDataType {
|
||||
dir: string
|
||||
expire: string
|
||||
host: string
|
||||
accessId: string
|
||||
policy: string
|
||||
signature: string
|
||||
}
|
||||
|
||||
const fileList = ref<UploadFile[]>([])
|
||||
const ossData = ref<OSSDataType | null>(null)
|
||||
|
||||
function mockOSSData() {
|
||||
return Promise.resolve({
|
||||
dir: 'user-dir/',
|
||||
expire: '1577811661',
|
||||
host: 'https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload',
|
||||
accessId: 'c2hhb2RhaG9uZw==',
|
||||
policy: 'eGl4aWhhaGFrdWt1ZGFkYQ==',
|
||||
signature: 'ZGFob25nc2hhbw==',
|
||||
})
|
||||
}
|
||||
|
||||
async function init() {
|
||||
try {
|
||||
ossData.value = await mockOSSData()
|
||||
}
|
||||
catch (err) {
|
||||
if (err instanceof Error) {
|
||||
message.error(err.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
|
||||
const handleChange: UploadEmits['change'] = ({ fileList: newFileList }) => {
|
||||
console.log('Aliyun OSS:', newFileList)
|
||||
fileList.value = [...newFileList]
|
||||
}
|
||||
|
||||
const handleRemove: UploadProps['onRemove'] = (file) => {
|
||||
fileList.value = fileList.value.filter(item => item.url !== file.url)
|
||||
}
|
||||
|
||||
const getExtraData: UploadProps['data'] = file => ({
|
||||
key: file.url,
|
||||
OSSAccessKeyId: ossData.value?.accessId,
|
||||
policy: ossData.value?.policy,
|
||||
Signature: ossData.value?.signature,
|
||||
})
|
||||
|
||||
const beforeUpload: UploadProps['beforeUpload'] = async (file) => {
|
||||
if (!ossData.value) {
|
||||
return false
|
||||
}
|
||||
|
||||
const expire = Number(ossData.value.expire) * 1000
|
||||
if (expire < Date.now()) {
|
||||
await init()
|
||||
}
|
||||
|
||||
const suffix = file.name.slice(file.name.lastIndexOf('.'))
|
||||
const filename = Date.now() + suffix
|
||||
;(file as UploadFile).url = ossData.value.dir + filename
|
||||
|
||||
return file
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-form :label-col="{ span: 4 }">
|
||||
<a-form-item label="Photos" name="photos">
|
||||
<a-upload
|
||||
v-model:file-list="fileList"
|
||||
name="file"
|
||||
:action="ossData?.host"
|
||||
:data="getExtraData"
|
||||
:before-upload="beforeUpload"
|
||||
:on-remove="handleRemove"
|
||||
@change="handleChange"
|
||||
>
|
||||
<a-button>
|
||||
<template #icon>
|
||||
<UploadOutlined />
|
||||
</template>
|
||||
Click to Upload
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</template>
|
||||
```
|
||||
@@ -0,0 +1,217 @@
|
||||
---
|
||||
title: Upload
|
||||
description: Used to select and upload files or drag and drop files.
|
||||
---
|
||||
|
||||
## When To Use
|
||||
Uploading is the process of publishing information (web pages, text, pictures, video, etc.) to a remote server via a web page or upload tool.
|
||||
|
||||
- When you need to upload one or more files.
|
||||
- When you need to show the process of uploading.
|
||||
- When you need to upload files by dragging and dropping.
|
||||
|
||||
## Demos
|
||||
|
||||
| Demo | Path |
|
||||
| --- | --- |
|
||||
| Upload by clicking | demo/basic.md |
|
||||
| Avatar | demo/avatar.md |
|
||||
| Default Files | demo/defaultFileList.md |
|
||||
| Pictures Wall | demo/picture-card.md |
|
||||
| Pictures with picture-circle type | demo/picture-circle.md |
|
||||
| Complete control over file list | demo/fileList.md |
|
||||
| Drag and Drop | demo/drag.md |
|
||||
| Paste | demo/paste.md |
|
||||
| Upload directory | demo/directory.md |
|
||||
| Upload manually | demo/upload-manually.md |
|
||||
| Upload png file only | demo/upload-png-only.md |
|
||||
| Pictures with list style | demo/picture-style.md |
|
||||
| Customize preview file | demo/preview-file.md |
|
||||
| Max Count | demo/max-count.md |
|
||||
| Transform file before request | demo/transform-file.md |
|
||||
| Aliyun OSS | demo/upload-with-aliyun-oss.md |
|
||||
| Custom show icon | demo/file-type.md |
|
||||
| Custom action icon and extra info | demo/upload-custom-action-icon.md |
|
||||
| Drag sorting of uploadList | demo/drag-sorting.md |
|
||||
| Crop image before uploading | demo/crop-image.md |
|
||||
| Customize Progress Bar | demo/customize-progress-bar.md |
|
||||
| Custom semantic dom styling | demo/style-class.md |
|
||||
| Component Token | demo/component-token.md |
|
||||
|
||||
## API
|
||||
|
||||
Common props ref:[Common props](../../docs/vue/common-props.md)
|
||||
|
||||
### Props
|
||||
|
||||
| Property | Description | Type | Default | Version | [Global Config](../config-provider/docs.md#component-config) |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| accept | File types that can be accepted. See [input accept Attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept) | string \| [AcceptObject](#acceptobject) | - | - | ✓ |
|
||||
| action | Uploading URL | string \| (file) => Promise<string> | - | - | × |
|
||||
| beforeUpload | Hook function which will be executed before uploading. Uploading will be stopped with `false` or a rejected Promise returned. When returned value is `Upload.LIST_IGNORE`, the list of files that have been uploaded will ignore it. **Warning:this function is not supported in IE9** | (file: [VcFile](#vcfile), fileList: [VcFile[]](#vcfile)) => boolean \| Promise<File> \| `Upload.LIST_IGNORE` | - | - | × |
|
||||
| customRequest | Override for the default xhr behavior allowing for additional customization and the ability to implement your own XMLHttpRequest | ( options: [RequestOptions](#request-options), info: \{ defaultRequest: (option: [RequestOptions](#request-options)) => void; \} ) => void | - | defaultRequest: - | ✓ |
|
||||
| data | Uploading extra params or function which can return uploading extra params | object \| (file) => object \| Promise<object> | - | - | × |
|
||||
| directory | Support upload whole directory ([caniuse](https://caniuse.com/#feat=input-file-directory)) | boolean | false | - | × |
|
||||
| disabled | Disable upload button. When customizing Upload children, please pass the `disabled` attribute to the child node at the same time to ensure the disabled rendering effect is consistent. | boolean | false | - | × |
|
||||
| fileList | List of files that have been uploaded (controlled). Here is a common issue [#2423](https://github.com/ant-design/ant-design/issues/2423) when using it, support `v-model:file-list` | [UploadFile](#uploadfile)\[] | - | - | × |
|
||||
| headers | Set request headers, valid above IE10 | object | - | - | × |
|
||||
| iconRender | Custom show icon | (file: UploadFile, listType?: UploadListType) => VueNode | - | - | × |
|
||||
| isImageUrl | Customize if render <img /> in thumbnail | (file: UploadFile) => boolean | [(inside implementation)](https://github.com/ant-design/ant-design/blob/4ad5830eecfb87471cd8ac588c5d992862b70770docs.md/utils.tsx#L47-L68) | - | × |
|
||||
| itemRender | Custom item of uploadList | (originNode: VueNode, file: UploadFile, fileList: object\[], actions: \{ download: function, preview: function, remove: function \}) => VueNode | - | - | × |
|
||||
| listType | Built-in stylesheets, support for four types: `text`, `picture`, `picture-card` or `picture-circle` | string | `text` | - | × |
|
||||
| maxCount | Limit the number of uploaded files. Will replace current one when `maxCount` is `1` | number | - | - | × |
|
||||
| method | The http method of upload request | string | `post` | - | × |
|
||||
| multiple | Whether to support selected multiple files. `IE10+` supported. You can select multiple files with CTRL holding down while multiple is set to be true | boolean | false | - | × |
|
||||
| name | The name of uploading file | string | `file` | - | × |
|
||||
| openFileDialogOnClick | Click open file dialog | boolean | true | - | × |
|
||||
| pastable | Support paste file | boolean | false | - | × |
|
||||
| previewFile | Customize preview file logic | (file: File \| Blob) => Promise<dataURL: string> | - | - | × |
|
||||
| progress | Custom progress bar | [ProgressProps](../progress/docs.md#api) (support `type="line"` only) | \{ strokeWidth: 2, showInfo: false \} | - | ✓ |
|
||||
| showUploadList | Whether to show default upload list, could be an object to specify `extra`, `showPreviewIcon`, `showRemoveIcon`, `showDownloadIcon`, `removeIcon` and `downloadIcon` individually | boolean \| \{ extra?: VueNode \| (file: UploadFile) => VueNode, showPreviewIcon?: boolean \| (file: UploadFile) => boolean, showDownloadIcon?: boolean \| (file: UploadFile) => boolean, showRemoveIcon?: boolean \| (file: UploadFile) => boolean, previewIcon?: VueNode \| (file: UploadFile) => VueNode, removeIcon?: VueNode \| (file: UploadFile) => VueNode, downloadIcon?: VueNode \| (file: UploadFile) => VueNode \} | true | `extra`: -, `showPreviewIcon` function: -, `showRemoveIcon` function: -, `showDownloadIcon` function: - | × |
|
||||
| withCredentials | The ajax upload with cookie sent | boolean | false | - | × |
|
||||
|
||||
### Events
|
||||
|
||||
| Event | Description | Type | Version |
|
||||
| --- | --- | --- | --- |
|
||||
| change | A callback function, can be executed when uploading state is changing. It will trigger by every uploading phase. see [onChange](#onchange) | function | - |
|
||||
| drop | A callback function executed when files are dragged and dropped into the upload area | (event: DragEvent) => void | - |
|
||||
| download | Click the method to download the file, pass the method to perform the method logic, and do not pass the default jump to the new TAB | function(file): void | (Jump to new TAB) |
|
||||
| preview | A callback function, will be executed when the file link or preview icon is clicked | function(file) | - |
|
||||
| remove | A callback function, will be executed when removing file button is clicked, remove event will be prevented when the return value is false or a Promise which resolve(false) or reject | function(file): boolean \| Promise | - |
|
||||
|
||||
### Slots
|
||||
|
||||
| Slot | Description | Type | Version |
|
||||
| --- | --- | --- | --- |
|
||||
| itemRender | Custom item of uploadList | ( ctx:\{ originNode: VNode, file: UploadFile, fileList: object\[], actions: \{ download: function, preview: function, remove: function \}\}) => VueNode | - |
|
||||
| iconRender | Custom show icon | (ctx:\{ file: UploadFile, listType?: UploadListType\}) => VueNode | - |
|
||||
|
||||
## Types
|
||||
|
||||
### VcFile
|
||||
Extends [File](https://developer.mozilla.org/en-US/docs/Web/API/File).
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| uid | unique id. Will auto-generate when not provided | string | - | - |
|
||||
| lastModifiedDate | A Date object indicating the date and time at which the file was last modified | date | - | - |
|
||||
|
||||
### UploadFile
|
||||
Extends [File](https://developer.mozilla.org/en-US/docs/Web/API/File) with additional props.
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| crossOrigin | CORS settings attributes | `'anonymous'` \| `'use-credentials'` \| `''` | - | - |
|
||||
| name | File name | string | - | - |
|
||||
| percent | Upload progress percent | number | - | - |
|
||||
| status | Upload status. Show different style when configured | `error` \| `done` \| `uploading` \| `removed` | - | - |
|
||||
| thumbUrl | Thumb image url | string | - | - |
|
||||
| uid | unique id. Will auto-generate when not provided | string | - | - |
|
||||
| url | Download url | string | - | - |
|
||||
|
||||
### RequestOptions
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| action | Uploading URL | string | - | - |
|
||||
| data | Uploading extra params or function which can return uploading extra params | Record<string, unknown> | - | - |
|
||||
| filename | file name | string | - | - |
|
||||
| file | File object containing upload information | [UploadFile](#uploadfile) | - | - |
|
||||
| withCredentials | The ajax upload with cookie sent | boolean | - | - |
|
||||
| headers | Set request headers, valid above IE10 | Record<string, string> | - | - |
|
||||
| method | The http method of upload request | string | - | - |
|
||||
| onProgress | Progress event callback | (event: object, file: UploadFile) => void | - | - |
|
||||
| onError | Error callback when upload fails | (event: object, body?: object) => void | - | - |
|
||||
| onSuccess | Success callback when upload completes | (body: object, fileOrXhr?: UploadFile \| XMLHttpRequest) => void | - | - |
|
||||
|
||||
### onChange
|
||||
> 💡 The function will be called when uploading is in progress, completed, or failed.
|
||||
|
||||
When uploading state change, it returns:
|
||||
|
||||
```ts
|
||||
{
|
||||
file: { /* ... */ },
|
||||
fileList: [ /* ... */ ],
|
||||
event: { /* ... */ },
|
||||
}
|
||||
```
|
||||
|
||||
1. `file` File object for the current operation.
|
||||
|
||||
```ts
|
||||
{
|
||||
uid: 'uid', // unique identifier, negative is recommended, // to prevent interference with internally generated id
|
||||
name: 'xx.png', // file name
|
||||
status: 'done' | 'uploading' | 'error' | 'removed', // Intercepted file by beforeUpload doesn't have a status field.
|
||||
response: '{"status": "success"}', // response from server
|
||||
linkProps: '{"download": "image"}', // additional HTML props of file link
|
||||
xhr: 'XMLHttpRequest{ ... }', // XMLHttpRequest Header
|
||||
}
|
||||
```
|
||||
|
||||
2. `fileList` current list of files
|
||||
|
||||
3. `event` response from the server, including uploading progress, supported by advanced browsers.
|
||||
|
||||
### AcceptObject
|
||||
```ts
|
||||
{
|
||||
format: string;
|
||||
filter?: 'native' | ((file: VcFile) => boolean);
|
||||
}
|
||||
```
|
||||
|
||||
Configuration object for file type acceptance rules.
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| format | Accepted file types, same as native input accept attribute. Supports MIME types, file extensions, etc. See [input accept Attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#accept) | string | - | - |
|
||||
| filter | File filtering rule. When set to `'native'`, uses browser native filtering behavior; when set to a function, allows custom filtering logic. Function returns `true` to accept the file, `false` to reject | `'native'` \| `(file: VcFile) => boolean` | - | - |
|
||||
|
||||
## Semantic DOM
|
||||
|
||||
| _semantic | demo/_semantic.md |
|
||||
|
||||
## FAQ
|
||||
|
||||
### How do I implement upload server side?
|
||||
- You can consult [jQuery-File-Upload](https://github.com/blueimp/jQuery-File-Upload/wiki#server-side) about how to implement server side upload interface.
|
||||
- There is a mock example of [express](https://github.com/react-component/upload/blob/211979fdaa2c7896b6496df7061a0cfc0fc5434e/server.js) in rc-upload.
|
||||
|
||||
### I want to display download links.
|
||||
Please set property `url` of each item in `fileList` to control the content of the link.
|
||||
|
||||
### How to use `customRequest`?
|
||||
See <https://github.com/react-component/upload#customrequest>.
|
||||
|
||||
### Why will the `fileList` that's in control not trigger `onChange` `status` update when the file is not in the list?
|
||||
`onChange` will only trigger when the file is in the list, it will ignore any events removed from the list.
|
||||
|
||||
### Why does `onChange` sometimes return File object and other times return `{ originFileObj: File }`? {#faq-on-change-return-type}
|
||||
|
||||
For compatible case, we return File object when `beforeUpload` return `false`. It will merge to `{ originFileObj: File }` in the next major version. Current version is compatible to get origin file by `info.file.originFileObj`. You can change this before a major release.
|
||||
|
||||
### Why sometimes Chrome can not upload?
|
||||
Chrome update will also break native upload. Please restart Chrome to finish the upload job.
|
||||
|
||||
<img alt="click restart button on Chrome" src="https://github.com/ant-design/ant-design/assets/507615/1509b25f-4cd3-41b2-9415-90394ad08273" width="800" />
|
||||
|
||||
Ref:
|
||||
|
||||
- [#48007](https://github.com/ant-design/ant-design/issues/48007)
|
||||
- [#32672](https://github.com/ant-design/ant-design/issues/32672)
|
||||
- [#32913](https://github.com/ant-design/ant-design/issues/32913)
|
||||
- [#33988](https://github.com/ant-design/ant-design/issues/33988)
|
||||
|
||||
### Can still select files when uploading a folder in Safari?
|
||||
Inside the upload component, we use the `directory` and `webkitdirectory` properties to control the input to implement folder selection, but it seems that in Safari's implementation, [it doesn't prevent users from selecting files](https://stackoverflow.com/q/55649945/3040605). You can solve this issue through `accept` configuration, for example:
|
||||
|
||||
```ts
|
||||
accept = {
|
||||
// Do not allow selecting any files
|
||||
format: `.${'n'.repeat(100)}`,
|
||||
// Accept all files within the folder after folder selection
|
||||
filter: () => true,
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,27 @@
|
||||
# upload Token
|
||||
|
||||
Use these variables through `theme.components.Upload`. This document lists definitions only and does not include values.
|
||||
|
||||
```vue
|
||||
<a-config-provider
|
||||
:theme="{
|
||||
token: {
|
||||
// Global token configuration
|
||||
},
|
||||
components: {
|
||||
Upload: {
|
||||
// Token name: value
|
||||
},
|
||||
},
|
||||
}"
|
||||
>
|
||||
...
|
||||
</a-config-provider>
|
||||
```
|
||||
|
||||
## Token List
|
||||
|
||||
| Token | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `actionsColor` | `string` | Action button color |
|
||||
| `pictureCardSize` | `number` | Size of list items in card type (affects both picture-card and picture-circle) |
|
||||
Reference in new issue
Block a user