Vant3 Uploader 文件上传

2021-09-09 16:51 更新

介绍

用于将本地的图片或文件上传至服务器,并在上传过程中展示预览图和上传进度。目前 Uploader 组件不包含将文件上传至服务器的接口逻辑,该步骤需要自行实现。

实例演示

引入

通过以下方式来全局注册组件,更多注册方式请参考组件注册

import { createApp } from 'vue';
import { Uploader } from 'vant';

const app = createApp();
app.use(Uploader);

代码演示

基础用法

文件上传完毕后会触发 after-read 回调函数,获取到对应的 file 对象。

<van-uploader :after-read="afterRead" />
export default {
  setup() {
    const afterRead = (file) => {
      // 此时可以自行将文件上传至服务器
      console.log(file);
    };

    return {
      afterRead,
    };
  },
};

文件预览

通过 v-model 可以绑定已经上传的文件列表,并展示文件列表的预览图。

<van-uploader v-model="fileList" multiple />
import { ref } from 'vue';

export default {
  setup() {
    const fileList = ref([
      { url: 'https://img.yzcdn.cn/vant/leaf.jpg' },
      // Uploader 根据文件后缀来判断是否为图片文件
      // 如果图片 URL 中不包含类型信息,可以添加 isImage 标记来声明
      { url: 'https://cloud-image', isImage: true },
    ]);

    return {
      fileList,
    };
  },
};

上传状态

通过 status 属性可以标识上传状态,uploading 表示上传中,failed 表示上传失败,done 表示上传完成。

<van-uploader v-model="fileList" :after-read="afterRead" />
import { ref } from 'vue';

export default {
  setup() {
    const fileList = ref([
      {
        url: 'https://img.yzcdn.cn/vant/leaf.jpg',
        status: 'uploading',
        message: '上传中...',
      },
      {
        url: 'https://img.yzcdn.cn/vant/tree.jpg',
        status: 'failed',
        message: '上传失败',
      },
    ]);

    const afterRead = (file) => {
      file.status = 'uploading';
      file.message = '上传中...';

      setTimeout(() => {
        file.status = 'failed';
        file.message = '上传失败';
      }, 1000);
    };

    return {
      fileList,
      afterRead,
    };
  },
};

限制上传数量

通过 max-count 属性可以限制上传文件的数量,上传数量达到限制后,会自动隐藏上传区域。

<van-uploader v-model="fileList" multiple :max-count="2" />
import { ref } from 'vue';

export default {
  setup() {
    const fileList = ref([]);

    return {
      fileList,
    };
  },
};

限制上传大小

通过 max-size 属性可以限制上传文件的大小,超过大小的文件会被自动过滤,这些文件信息可以通过 oversize 事件获取。

<van-uploader multiple :max-size="500 * 1024" @oversize="onOversize" />
import { Toast } from 'vant';

export default {
  setup() {
    const onOversize = (file) => {
      console.log(file);
      Toast('文件大小不能超过 500kb');
    };

    return {
      onOversize,
    };
  },
};

如果需要针对不同类型的文件来作出不同的大小限制,可以在 max-size 属性中传入一个函数,在函数中通过 file.type 区分文件类型,返回 true 表示超出限制,false 表示未超出限制。

<van-uploader multiple :max-size="isOverSize" />
import { Toast } from 'vant';

export default {
  setup() {
    const isOverSize = (file) => {
      const maxSize = file.type === 'image/jpeg' ? 500 * 1024 : 1000 * 1024;
      return file.size >= maxSize;
    };
    return {
      isOverSize,
    };
  },
};

自定义上传样式

通过默认插槽可以自定义上传区域的样式。

<van-uploader>
  <van-button icon="plus" type="primary">上传文件</van-button>
</van-uploader>

自定义预览样式

通过 preview-cover 插槽可以自定义覆盖在预览区域上方的内容。

<van-uploader v-model="fileList">
  <template #preview-cover="{ file }">
    <div class="preview-cover van-ellipsis">{{ file.name }}</div>
  </template>
</van-uploader>

<style>
  .preview-cover {
    position: absolute;
    bottom: 0;
    box-sizing: border-box;
    width: 100%;
    padding: 4px;
    color: #fff;
    font-size: 12px;
    text-align: center;
    background: rgba(0, 0, 0, 0.3);
  }
</style>

上传前置处理

通过传入 beforeRead 函数可以在上传前进行校验和处理,返回 true 表示校验通过,返回 false 表示校验失败。支持返回 Promise 对 file 对象进行自定义处理,例如压缩图片。

<van-uploader :before-read="beforeRead" />
import { Toast } from 'vant';

export default {
  setup() {
    // 返回布尔值
    const beforeRead = (file) => {
      if (file.type !== 'image/jpeg') {
        Toast('请上传 jpg 格式图片');
        return false;
      }
      return true;
    };

    // 返回 Promise
    const asyncBeforeRead = (file) => {
      return new Promise((resolve, reject) => {
        if (file.type !== 'image/jpeg') {
          Toast('请上传 jpg 格式图片');
          reject();
        } else {
          const img = new File(['foo'], 'bar.jpg', {
            type: 'image/jpeg',
          });
          resolve(img);
        }
      });
    };

    return {
      beforeRead,
      asyncBeforeRead,
    };
  },
};

禁用文件上传

通过 disabled 属性禁用文件上传。

<van-uploader disabled />

自定义单个图片预览

在 v-model 数组中设置单个预览图片属性,支持 imageFit deletable previewSize beforeDelete。

<van-uploader v-model="fileList" :deletable="false" />
import { ref } from 'vue';
import { Toast } from 'vant';

export default {
  setup() {
    const fileList = ref([
      { url: 'https://img.yzcdn.cn/vant/leaf.jpg' },
      {
        url: 'https://img.yzcdn.cn/vant/sand.jpg',
        deletable: true,
        beforeDelete: () => {
          Toast('自定义单个预览图片的事件和样式');
        },
      },
      {
        url: 'https://img.yzcdn.cn/vant/tree.jpg',
        deletable: true,
        imageFit: 'contain',
        previewSize: 120,
      },
    ]);

    return { fileList };
  },
};

API

Props

参数 说明 类型 默认值
v-model 已上传的文件列表 FileListItem[] -
accept 允许上传的文件类型,详细说明 string image/*
name 标识符,可以在回调函数的第二项参数中获取 number | string -
preview-size 预览图和上传区域的尺寸,默认单位为 px number | string 80px
preview-image 是否在上传完成后展示预览图 boolean true
preview-full-image 是否在点击预览图后展示全屏图片预览 boolean true
preview-options 全屏图片预览的配置项,可选值见 ImagePreview object -
multiple 是否开启图片多选,部分安卓机型不支持 boolean false
disabled 是否禁用文件上传 boolean false
readonly v3.1.5 是否将上传区域设置为只读状态 boolean false
deletable 是否展示删除按钮 boolean true
show-upload 是否展示上传区域 boolean true
lazy-load 是否开启图片懒加载,须配合 Lazyload 组件使用 boolean false
capture 图片选取模式,可选值为 camera (直接调起摄像头) string -
after-read 文件读取完成后的回调函数 Function -
before-read 文件读取前的回调函数,返回 false 可终止文件读取,
支持返回 Promise
Function -
before-delete 文件删除前的回调函数,返回 false 可终止文件读取,
支持返回 Promise
Function -
max-size v3.0.17 文件大小限制,单位为 byte number | string | (file: File) => boolean -
max-count 文件上传数量限制 number | string -
result-type 文件读取结果类型,可选值为 file text string dataUrl
upload-text 上传区域文字提示 string -
image-fit 预览图裁剪模式,可选值见 Image 组件 string cover
upload-icon 上传区域图标名称或图片链接 string photograph
注意:accept、capture 和 multiple 为浏览器 input 标签的原生属性,移动端各种机型对这些属性的支持程度有所差异,因此在不同机型和 WebView 下可能出现一些兼容性问题。

Events

事件名 说明 回调参数
oversize 文件大小超过限制时触发 同 after-read
click-upload v3.1.5 点击上传区域时触发 event: MouseEvent
click-preview 点击预览图时触发 同 after-read
close-preview 关闭全屏图片预览时触发 -
delete 删除文件预览时触发 同 after-read

Slots

名称 说明 参数
default 自定义上传区域 -
preview-cover 自定义覆盖在预览区域上方的内容 item: FileListItem

回调参数

before-read、after-read、before-delete 执行时会传递以下回调参数:

参数名 说明 类型
file file 对象 object
detail 额外信息,包含 name 和 index 字段 object

ResultType 可选值

result-type 字段表示文件读取结果的类型,上传大文件时,建议使用 file 类型,避免卡顿。

描述
file 结果仅包含 File 对象
text 结果包含 File 对象,以及文件的文本内容
dataUrl 结果包含 File 对象,以及文件对应的 base64 编码

方法

通过 ref 可以获取到 Uploader 实例并调用实例方法,详见组件实例方法

方法名 说明 参数 返回值
closeImagePreview 关闭全屏的图片预览 - -
chooseFile 主动调起文件选择,由于浏览器安全限制,只有在用户触发操作的上下文中调用才有效 - -

类型定义

通过 UploaderInstance 获取 Uploader 实例的类型定义。

import { ref } from 'vue';
import type { UploaderInstance } from 'vant';

const uploaderRef = ref<UploaderInstance>();

uploaderRef.value?.chooseFile();

样式变量

组件提供了下列 CSS 变量,可用于自定义样式,使用方法请参考  ConfigProvider 组件

名称 默认值 描述
--van-uploader-size 80px -
--van-uploader-icon-size 24px -
--van-uploader-icon-color var(--van-gray-4) -
--van-uploader-text-color var(--van-gray-6) -
--van-uploader-text-font-size var(--van-font-size-sm) -
--van-uploader-upload-background-color var(--van-gray-1) -
--van-uploader-upload-active-color var(--van-active-color) -
--van-uploader-delete-color var(--van-white) -
--van-uploader-delete-icon-size 14px -
--van-uploader-delete-background-color rgba(0, 0, 0, 0.7) -
--van-uploader-file-background-color var(--van-background-color) -
--van-uploader-file-icon-size 20px -
--van-uploader-file-icon-color var(--van-gray-7) -
--van-uploader-file-name-padding 0 var(--van-padding-base) -
--van-uploader-file-name-margin-top var(--van-padding-xs) -
--van-uploader-file-name-font-size var(--van-font-size-sm) -
--van-uploader-file-name-text-color var(--van-gray-7) -
--van-uploader-mask-text-color var(--van-white) -
--van-uploader-mask-background-color fade(var(--van-gray-8), 88%) -
--van-uploader-mask-icon-size 22px -
--van-uploader-mask-message-font-size var(--van-font-size-sm) -
--van-uploader-mask-message-line-height var(--van-line-height-xs) -
--van-uploader-loading-icon-size 22px -
--van-uploader-loading-icon-color var(--van-white) -
--van-uploader-disabled-opacity var(--van-disabled-opacity) -

常见问题

拍照上传的图片被旋转 90 度?

部分手机在拍照上传时会出现图片被旋转 90 度的问题,这个问题可以通过 compressorjs 或其他开源库进行处理。

compressorjs 是一个开源的图片处理库,提供了图片压缩、图片旋转等能力。

示例

使用 compressorjs 进行处理的示例代码如下:

<van-uploader :before-read="beforeRead" />
import Compressor from 'compressorjs';

export default {
  setup() {
    const beforeRead = (file) => {
      return new Promise((resolve) => {
        // compressorjs 默认开启 checkOrientation 选项
        // 会将图片修正为正确方向
        new Compressor(file, {
          success: resolve,
          error(err) {
            console.log(err.message);
          },
        });
      });
    };

    return {
      beforeRead,
    };
  },
};

上传 HEIC/HEIF 格式的图片后无法展示?

目前 Chrome、Safari 等浏览器不支持展示 HEIC/HEIF 格式的图片,因此上传后无法在 Uploader 组件中进行预览。

[HEIF] 格式的兼容性请参考 caniuse


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号