Skip to content

Upload Component

This component is used for file upload scenarios, supporting uploads of various file types such as images and videos

📌 Platform Differences

APP(vue)H5WeChat Mini ProgramAlipay Mini Program

🏯 Basic Usage

html
<!-- Global usage -->
<hy-upload :fileList="list"></hy-upload>

Basic Upload

html
<template>
    <hy-upload :fileList="list" @afterRead="afterRead"></hy-upload>
</template>
ts
import { ref } from 'vue';
import type { FileVo } from '@/package/components/hy-upload/typing';

const list = ref<FileVo[]>([]);

const afterRead = (event: any) => {
    const file = event.file;
    list.value.push({
        status: 'loading',
        message: 'Uploading',
        url: file.url,
        schedule: 0,
    });
    // Simulate upload progress
    let progress = 0;
    const timer = setInterval(() => {
        progress += 10;
        list.value[0].schedule = progress;
        if (progress >= 100) {
            clearInterval(timer);
            list.value[0].status = 'success';
            list.value[0].message = 'Upload successful';
        }
    }, 200);
};

Limiting Upload Count

Set the maximum number of uploads via maxCount; the default is 52.

html
<hy-upload :fileList="list" :maxCount="3" @afterRead="afterRead"></hy-upload>

Multiple Image Upload

Set multiple to enable multi-select mode; not supported on some Android devices.

html
<hy-upload :fileList="list" multiple @afterRead="afterRead"></hy-upload>
ts
import { ref } from 'vue';
import type { FileVo } from '@/package/components/hy-upload/typing';
import { isArray } from '@/package';

const list = ref<FileVo[]>([]);

const afterRead = (event: any) => {
    const files = event.file;
    if (isArray(files)) {
        files.forEach((item) => {
            list.value.push({
                status: 'loading',
                message: 'Uploading',
                url: item.url,
                schedule: 0,
            });
            // Simulate a single file upload
            const index = list.value.findIndex((v) => v.url === item.url);
            let progress = 0;
            const timer = setInterval(() => {
                progress += 10;
                list.value[index].schedule = progress;
                if (progress >= 100) {
                    clearInterval(timer);
                    list.value[index].status = 'success';
                    list.value[index].message = 'Upload successful';
                }
            }, 200);
        });
    }
};

Limiting File Size

Use maxSize to set the maximum size of a single file, in bytes (byte).

html
<template>
    <hy-upload
        :fileList="list"
        :maxSize="500000"
        @afterRead="afterRead"
        @oversize="onOversize"
    ></hy-upload>
</template>

<script setup lang="ts">
    import { ref } from 'vue';
    import type { FileVo } from '@/package/components/hy-upload/typing';

    const list = ref<FileVo[]>([]);

    const afterRead = (event) => {
        // Handle upload logic
    };

    const onOversize = () => {
        uni.showToast({
            title: 'Image exceeds the 500KB limit',
            icon: 'none',
        });
    };
</script>

Uploading Videos

Set accept="video" to restrict uploads to video files only.

html
<template>
    <hy-upload :fileList="list" accept="video" :maxDuration="30" @afterRead="afterRead"></hy-upload>
</template>

<script setup lang="ts">
    import { ref } from 'vue';
    import type { FileVo } from '@/package/components/hy-upload/typing';

    const list = ref<FileVo[]>([]);

    const afterRead = (event) => {
        const file = event.file as FileVo;
        list.value.push({
            type: 'video',
            status: 'success',
            message: 'Upload successful',
            url: file.url,
        });
    };
</script>

Custom Upload Button

Use the default slot to customize the upload button style.

html
<template>
    <hy-upload :fileList="list" @afterRead="afterRead">
        <view class="custom-upload-btn">
            <hy-icon name="plus" color="#999" size="32"></hy-icon>
            <text class="custom-upload-text">Click to upload</text>
        </view>
    </hy-upload>
</template>

<style scoped lang="scss">
    .custom-upload-btn {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        width: 160rpx;
        height: 160rpx;
        border: 2rpx dashed #d9d9d9;
        border-radius: 12rpx;

        .custom-upload-text {
            font-size: 24rpx;
            color: #999;
            margin-top: 8rpx;
        }
    }
</style>

Custom Trigger Area

Use the trigger slot to customize the area that triggers the upload.

html
<template>
    <hy-upload :fileList="list" @afterRead="afterRead">
        <template #trigger>
            <view class="custom-trigger">
                <hy-icon name="upload" color="#2979ff" size="48"></hy-icon>
                <text class="custom-trigger-text">Drag or click to upload</text>
            </view>
        </template>
    </hy-upload>
</template>

<style scoped lang="scss">
    .custom-trigger {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        width: 100%;
        height: 200rpx;
        border: 2rpx dashed #2979ff;
        border-radius: 12rpx;
        background: rgba(41, 121, 255, 0.05);

        .custom-trigger-text {
            font-size: 28rpx;
            color: #2979ff;
            margin-top: 12rpx;
        }
    }
</style>

Disabled State

Set disabled to disable the upload functionality.

html
<template>
    <hy-upload :fileList="list" disabled>
        <view class="disabled-btn">
            <hy-icon name="lock" color="#ccc" size="24"></hy-icon>
            <text class="disabled-text">Upload is disabled</text>
        </view>
    </hy-upload>
</template>

Hiding the Delete Button

Set deletable="false" to hide the delete button.

html
<hy-upload :fileList="list" :deletable="false" @afterRead="afterRead"></hy-upload>

Custom Size

Customize the size of the upload area via width and height.

html
<hy-upload
    :fileList="list"
    :width="120"
    :height="120"
    upload-text="Large size"
    @afterRead="afterRead"
></hy-upload>

Upload Failed State

Set status="failed" to display the upload failed state.

html
<template>
    <hy-upload :fileList="list"></hy-upload>
</template>

<script setup lang="ts">
    import { ref } from 'vue';
    import type { FileVo } from '@/package/components/hy-upload/typing';

    const list = ref<FileVo[]>([
        {
            status: 'failed',
            message: 'Upload failed',
            url: '',
        },
    ]);
</script>

Image Cropping Mode

Use imageMode to set the cropping mode of the preview image, consistent with the mode attribute of the image component.

html
<hy-upload :fileList="list" imageMode="aspectFit"></hy-upload>

Controlling Preview

Use previewFullImage to control whether the fullscreen preview feature is displayed.

html
<hy-upload :fileList="list" :previewFullImage="false"></hy-upload>

Selection Mode

Use capture to set the capture mode for images or videos.

html
<!-- Select from album only -->
<hy-upload :fileList="list" :capture="['album']"></hy-upload>

<!-- Camera capture only -->
<hy-upload :fileList="list" :capture="['camera']"></hy-upload>

<!-- Support both album and camera -->
<hy-upload :fileList="list" :capture="['album', 'camera']"></hy-upload>

Original/Compressed Images

Use sizeType to control the size type of the selected images.

html
<!-- Select original images only -->
<hy-upload :fileList="list" :sizeType="['original']"></hy-upload>

<!-- Select compressed images only -->
<hy-upload :fileList="list" :sizeType="['compressed']"></hy-upload>

<!-- Support both original and compressed images -->
<hy-upload :fileList="list" :sizeType="['original', 'compressed']"></hy-upload>

API

Upload Props

ParameterDescriptionTypeDefault Value
acceptAccepted file types; file is only supported on H5 (only the WeChat Mini Program supports setting accept to all or media)stringimage
extensionFilters by file extension; no item may be an empty string. No filtering by default.string[][]
captureImage or video capture mode; when accept is of image type, setting the additional option camera in capture will directly invoke the camera('album' | 'camera')[]['album', 'camera']
compressedTakes effect when accept is video; whether to compress the videobooleantrue
cameraTakes effect when accept is video; optional values are back or front'back' | 'front'back
maxDurationTakes effect when accept is video; the maximum recording duration for shooting a video, in secondsnumber60
uploadIconIcon for the upload area; only built-in icons are supportedstringIconConfig.UPLOAD
uploadIconColorColor of the icon in the upload areastring#D3D4D6
useBeforeReadWhether to enable the before-read eventbooleanfalse
previewFullImageWhether to display the component's built-in image previewbooleantrue
maxCountMaximum number of uploadsnumber52
disabledWhether to disable the componentbooleanfalse
imageModeCropping mode when previewing uploaded images, consistent with the image component's mode attributestringaspectFill
nameIdentifier, which can be retrieved in the second parameter of callback functionsstring''
sizeTypeoriginal for original images, compressed for compressed images; both by default; not effective on H5('original' | 'compressed')[]['original', 'compressed']
multipleWhether to enable multiple image selection; not supported on some Android devicesbooleanfalse
deletableWhether to show the delete image buttonbooleantrue
maxSizeMaximum size of a single selected file, in B (byte); no limit by defaultnumberNumber.MAX_VALUE
fileListList of already uploaded files to displayFileVo[][]
uploadTextHint text for the upload areastring''
widthWidth of the internal preview image area and the image selection button area; numeric values default to the unit rpxstring | number80
heightHeight of the internal preview image area and the image selection button area; numeric values default to the unit rpxstring | number80
beforeReadHandler function before reading(file, detail) => void-
afterReadHandler function after reading(file, detail) => void-
customStyleCustom external styles to applyCSSProperties-

fileList Data Structure

ParameterDescriptionTypeDefault Value
urlLocal URL of the uploaded filestring-
typeUploaded file type'image' | 'video' | 'file'-
thumbThumbnail URLstring-
sizeFile sizenumber-
isVideoWhether it is a videoboolean-
isImageWhether it is an imageboolean-
deletableWhether to show the delete buttonboolean-
statusUpload status'loading' | 'failed' | 'success'-
messageHint messagestring-
scheduleUpload progressstring | number-

Events

Event NameDescriptionCallback Parameters
afterReadHandler function after the file is read{ file: FileVo | FileVo[], name: string, index: number }
beforeReadHandler function before the file is read{ file: FileVo | FileVo[], name: string, index: number, callback: (ok) => void }
oversizeFile size exceeds the maximum allowed size{ file: FileVo | FileVo[], name: string, index: number }
clickPreviewTriggered when an image is previewed in fullscreen{ file: FileVo, name: string, index: number }
deleteTriggered when an image is deleted{ file: FileVo, name: string, index: number }
errorTriggered on upload errorerror: any

Slots

Slot NameDescription
defaultCustom upload button content
triggerCustom area that triggers the upload

Typings

Type Definitions
ts
export interface FileVo {
    /** Local URL of the uploaded file */
    url?: string;
    /** Uploaded file type */
    type?: 'image' | 'video' | 'file';
    /** Thumbnail URL */
    thumb?: string;
    /** File size */
    size?: number;
    /** Whether it is a video */
    isVideo?: boolean;
    /** Whether it is an image */
    isImage?: boolean;
    /** Whether to show the delete button */
    deletable?: boolean;
    /** Upload status */
    status?: 'loading' | 'failed' | 'success';
    /** Hint message */
    message?: string;
    /** Upload progress */
    schedule?: string | number;
}

export type ReadFunctionVo = (file: FileVo, detail: { name: string; index: number }) => void;

export interface UploadFileParams {
    file: FileVo | FileVo[];
    name: string;
    index: number;
}
03:29