Uploader 上传

示例

文件上传

设置 type 的值为 file 进入文件上传模式。

Normal size

  • demo-file1.txt
  • demo-file2.txt

Small size

  • demo-file1.txt
  • demo-file2.txt
在 GitHub 上编辑此示例编辑
<template>
<article>
  <section>
    <h4>Normal size</h4>
    <veui-uploader
      v-model="files"
      action="https://app.fakejson.com/q/ELymQ7xh?token=AWFkjMICPSAB_bO_z-Lnog"
    />
  </section>
  <section>
    <h4>Small size</h4>
    <veui-uploader
      v-model="files2"
      action="https://app.fakejson.com/q/ELymQ7xh?token=AWFkjMICPSAB_bO_z-Lnog"
      ui="s"
    />
  </section>
</article>
</template>

<script>
import { Uploader } from 'veui'
import { cloneDeep } from 'lodash'

export default {
  components: {
    'veui-uploader': Uploader
  },
  data () {
    let files = [
      {
        name: 'demo-file1.txt',
        src: '/file/demo-file1.txt',
        key: 0
      },
      {
        name: 'demo-file2.txt',
        src: '/file/demo-file2.txt',
        key: 1
      }
    ]
    return {
      files,
      files2: cloneDeep(files)
    }
  }
}
</script>

<style lang="less" scoped>
article {
  display: flex;
}

section {
  width: 45%;
}
</style>

图片上传

设置 type 的值为 image 进入图片上传模式。

Normal size

  • Normal size

Small size

  • Small size
在 GitHub 上编辑此示例编辑
<template>
<article>
  <section>
    <h4>Normal size</h4>
    <veui-uploader
      v-model="images"
      type="image"
      action="https://app.fakejson.com/q/ELymQ7xh?token=AWFkjMICPSAB_bO_z-Lnog"
    >
      <template #desc>
        Normal size
      </template>
    </veui-uploader>
  </section>
  <section>
    <h4>Small size</h4>
    <veui-uploader
      v-model="images2"
      type="image"
      action="https://app.fakejson.com/q/ELymQ7xh?token=AWFkjMICPSAB_bO_z-Lnog"
      ui="s"
    >
      <template #desc>
        Small size
      </template>
    </veui-uploader>
  </section>
</article>
</template>

<script>
import { Uploader } from 'veui'
import { cloneDeep } from 'lodash'

export default {
  components: {
    'veui-uploader': Uploader
  },
  data () {
    let images = [
      {
        src: '/images/development/uploader/demo-image1.jpg',
        key: 0
      },
      {
        src: '/images/development/uploader/demo-image2.jpg',
        key: 1
      }
    ]
    return {
      images,
      images2: cloneDeep(images)
    }
  }
}
</script>

媒体上传

设置 type 的值为 media 进入媒体上传模式。

Normal size

  • Normal size

Small size

  • Small size
在 GitHub 上编辑此示例编辑
<template>
<article>
  <section>
    <h4>Normal size</h4>
    <veui-uploader
      v-model="media"
      type="media"
      action="https://app.fakejson.com/q/ELymQ7xh?token=AWFkjMICPSAB_bO_z-Lnog"
    >
      <template #desc>
        Normal size
      </template>
    </veui-uploader>
  </section>
  <section>
    <h4>Small size</h4>
    <veui-uploader
      v-model="media2"
      type="media"
      action="https://app.fakejson.com/q/ELymQ7xh?token=AWFkjMICPSAB_bO_z-Lnog"
      ui="s"
    >
      <template #desc>
        Small size
      </template>
    </veui-uploader>
  </section>
</article>
</template>

<script>
import { Uploader } from 'veui'
import { cloneDeep } from 'lodash'

export default {
  components: {
    'veui-uploader': Uploader
  },
  data () {
    let media = [
      {
        type: 'image',
        src: '/images/development/uploader/demo-image1.jpg',
        key: 0
      },
      {
        type: 'video',
        src: 'https://nadvideo2.baidu.com/5dafd8544f4f53b27a5f59b0ab780403_1920_1080.mp4',
        poster: 'https://feed-image.baidu.com/0/pic/4dced79d185a16e228652b136f653dcc.jpg',
        key: 1
      }
    ]
    return {
      media,
      media2: cloneDeep(media)
    }
  }
}
</script>

前端校验

图片格式、大小、数量校验以及使用 validator 自定义校验。

  • 请选择jpg、png图片,大小不超过100kb,宽高分别大于200px,最多上传6张图片
在 GitHub 上编辑此示例编辑
<template>
<article>
  <section>
    <veui-uploader
      v-model="images"
      type="image"
      action="https://app.fakejson.com/q/ELymQ7xh?token=AWFkjMICPSAB_bO_z-Lnog"
      accept="jpg,png"
      :max-count="6"
      max-size="100kb"
      :validator="validator"
    >
      <template #desc>
        请选择jpg、png图片,大小不超过100kb,宽高分别大于200px,最多上传6张图片
      </template>
    </veui-uploader>
  </section>
</article>
</template>

<script>
import { Uploader } from 'veui'

export default {
  components: {
    'veui-uploader': Uploader
  },
  data () {
    return {
      images: [
        {
          src: '/images/development/uploader/demo-image1.jpg',
          key: 0
        },
        {
          src: '/images/development/uploader/demo-image2.jpg',
          key: 1
        }
      ],
      validator (file) {
        return new Promise(resolve => {
          let image = new Image()
          image.src = window.URL.createObjectURL(file)
          image.onload = () => {
            resolve({
              valid: image.height > 200 && image.width > 200,
              message: '图片宽高太小'
            })
          }
        })
      }
    }
  }
}
</script>

自定义配置

使用 upload 自定义上传过程,使用 controls 配置浮层操作项。

  • 点击图片浮层上的向右箭头按钮改变图片位置
在 GitHub 上编辑此示例编辑
<template>
<article>
  <section>
    <veui-uploader
      v-model="images"
      type="image"
      :action="action"
      :controls="controls"
      request-mode="custom"
      :upload="upload"
      @moveright="handleMoveRight"
    >
      <template #desc>
        点击图片浮层上的向右箭头按钮改变图片位置
      </template>
    </veui-uploader>
  </section>
</article>
</template>

<script>
import { Uploader } from 'veui'

export default {
  components: {
    'veui-uploader': Uploader
  },
  data () {
    return {
      action: 'https://app.fakejson.com/q/ELymQ7xh?token=AWFkjMICPSAB_bO_z-Lnog',
      images: [
        {
          key: 0,
          src: '/images/development/uploader/demo-image1.jpg'
        },
        {
          key: 1,
          src: '/images/development/uploader/demo-image2.jpg'
        }
      ],
      controls (file, defaultControls) {
        if (file.status === 'success') {
          return [
            { name: 'moveright', icon: 'chevron-right', disabled: false },
            ...defaultControls
          ]
        }
        return defaultControls
      },
      upload: (file, { onload, onprogress, onerror }) => {
        let xhr = new XMLHttpRequest()
        file.xhr = xhr

        xhr.upload.onprogress = e => onprogress(e)
        xhr.onload = e => {
          try {
            onload(JSON.parse(xhr.responseText))
          } catch (e) {
            onload({ success: false, message: e })
          }
        }
        xhr.onerror = e => onerror(e)
        let formData = new FormData()
        formData.append('file', file)

        xhr.open('POST', this.action, true)
        xhr.send(formData)

        return () => {
          xhr.abort()
        }
      }
    }
  },
  methods: {
    handleMoveRight (file, index) {
      if (index < this.images.length - 1) {
        let temp = { ...this.images[index] }
        this.$set(this.images, index, this.images[index + 1])
        this.$set(this.images, index + 1, temp)
      }
    }
  }
}
</script>

拖拽排序

设置 sortable 属性来指定上传项目之间可以拖拽排序。

在 GitHub 上编辑此示例编辑
<template>
<article>
  <section>
    <veui-uploader
      v-model="images"
      sortable
      type="image"
      action="https://app.fakejson.com/q/ELymQ7xh?token=AWFkjMICPSAB_bO_z-Lnog"
    />
  </section>
</article>
</template>

<script>
import { Uploader } from 'veui'

export default {
  components: {
    'veui-uploader': Uploader
  },
  data () {
    return {
      images: [
        {
          key: 0,
          src: '/images/development/uploader/demo-image1.jpg'
        },
        {
          key: 1,
          src: '/images/development/uploader/demo-image2.jpg'
        }
      ]
    }
  }
}
</script>

已上传项自定义操作

设置 controls 属性来指定悬浮到每个上传项时的操作选项。

controls 自定义的操作,点击会触发同名事件,事件参数为该上传项数据和 status 字段, 即通常是 {src, key, type, status, ...}

在 GitHub 上编辑此示例编辑
<template>
<article>
  <section>
    <veui-uploader
      v-model="images"
      :controls="controls"
      type="image"
      action="https://app.fakejson.com/q/ELymQ7xh?token=AWFkjMICPSAB_bO_z-Lnog"
      @star="handleStar"
    />
  </section>
</article>
</template>

<script>
import { Uploader, toast } from 'veui'
import 'veui-theme-dls-icons/star'

export default {
  components: {
    'veui-uploader': Uploader
  },
  data () {
    return {
      images: [
        {
          key: 0,
          src: '/images/development/uploader/demo-image1.jpg'
        },
        {
          key: 1,
          src: '/images/development/uploader/demo-image2.jpg'
        }
      ],
      controls (item, defaultControls) {
        return [
          ...defaultControls,
          {
            name: 'star',
            icon: 'star',
            label: 'star'
          }
        ]
      }
    }
  },
  methods: {
    handleStar () {
      toast.info('You click star!')
    }
  }
}
</script>

上传入口自定义操作

设置 entries 属性来指定悬浮到继续上传项目时的操作选项。

entries 自定义的操作,点击会触发同名事件,事件参数为空。

在 GitHub 上编辑此示例编辑
<template>
<article>
  <section>
    <veui-uploader
      v-model="images"
      :entries="entries"
      type="image"
      action="https://app.fakejson.com/q/ELymQ7xh?token=AWFkjMICPSAB_bO_z-Lnog"
      @star="handleStar"
    />
  </section>
</article>
</template>

<script>
import { Uploader, toast } from 'veui'
import 'veui-theme-dls-icons/star'

export default {
  components: {
    'veui-uploader': Uploader
  },
  data () {
    return {
      images: [
        {
          key: 0,
          src: '/images/development/uploader/demo-image1.jpg'
        },
        {
          key: 1,
          src: '/images/development/uploader/demo-image2.jpg'
        }
      ],
      entries (defaultEntries) {
        return [
          ...defaultEntries,
          {
            name: 'star',
            icon: 'star',
            label: 'star'
          }
        ]
      }
    }
  },
  methods: {
    handleStar () {
      toast.info('You clicked star!')
    }
  }
}
</script>

自定义选择文件

设置 pick 属性来自定义选择文件。

    在 GitHub 上编辑此示例编辑
    <template>
    <article>
      <section>
        <veui-uploader
          type="file"
          :pick="pick"
          action="https://app.fakejson.com/q/ELymQ7xh?token=AWFkjMICPSAB_bO_z-Lnog"
        />
      </section>
    </article>
    </template>
    
    <script>
    import { Uploader } from 'veui'
    import confirm from 'veui/plugins/confirm'
    import Vue from 'vue'
    
    Vue.use(confirm)
    
    export default {
      components: {
        'veui-uploader': Uploader
      },
      methods: {
        pick ({ remainingCount }) {
          return this.$confirm('模拟自定义选择文件', '确认').then((ready) => {
            return ready
              ? new File([`count: ${remainingCount}`], 'pick.txt', { type: 'text/plain' })
              : null
          })
        }
      }
    }
    </script>
    

    帮助文案

    设置 help 属性或help 插槽来指定帮助文案。

    辅助信息位置:
    Help text
    • demo-file1.txt
    Custom help text via `help` slot
    • demo-file1.txt
    在 GitHub 上编辑此示例编辑
    <template>
    <article>
      <section>
        <div>
          辅助信息位置:
          <veui-radio-button-group
            v-model="helpPosition"
            ui="s"
            :items="availableHelpPositions"
          />
        </div>
        <veui-uploader
          v-model="files"
          :help-position="helpPosition"
          help="Help text"
          action="https://app.fakejson.com/q/ELymQ7xh?token=AWFkjMICPSAB_bO_z-Lnog"
        />
        <veui-uploader
          v-model="files"
          :help-position="helpPosition"
          action="https://app.fakejson.com/q/ELymQ7xh?token=AWFkjMICPSAB_bO_z-Lnog"
        >
          <template #help>Custom help text via `help` slot</template>
        </veui-uploader>
      </section>
    </article>
    </template>
    
    <script>
    import { Uploader, RadioButtonGroup } from 'veui'
    
    const mapper = (value) => ({ label: value, value })
    
    export default {
      components: {
        'veui-uploader': Uploader,
        'veui-radio-button-group': RadioButtonGroup
      },
      data () {
        let files = [
          {
            name: 'demo-file1.txt',
            src: '/file/demo-file1.txt',
            key: 0
          }
        ]
        return {
          files,
          helpPosition: 'side',
          availableHelpPositions: ['side', 'bottom'].map(mapper)
        }
      }
    }
    </script>
    
    <style lang="less" scoped>
    article {
      display: flex;
    }
    
    .veui-uploader {
      margin-top: 16px;
    }
    
    section {
      width: 45%;
    }
    </style>
    

    API

    属性

    属性类型默认值描述
    uistring=-

    预设样式。

    描述
    s小尺寸样式。
    m中尺寸样式。
    typestring'file'

    上传类型。

    描述
    file文件上传。
    image图片上传。
    media媒体上传(支持视频和图片)。
    video视频上传。
    valueObject | Array<Object>-

    multipletrue,返回文件对象的数组。另外,当 max-count 被设置为大于 1 的值,则会视为开启了 multiple

    每个文件对象的类型为 {name: string, src: string, ...},以及在 convert-response 中自定义添加的字段。

    key-fieldstring'key'用于指定文件对象的唯一 key,作为数据变化时正确处理文件列表顺序的依据。
    namestring'file'原生 <input> 元素的 name
    actionstring-上传地址。
    headersObjectuploader.headers需要加入 HTTP 请求头 的内容。可进行全局统一配置
    with-credentialsbooleantrueXMLHttpRequestwithCredentials 属性。
    request-modestringuploader.requestMode

    指定异步上传方式。可进行全局统一配置

    描述
    xhr通过 XMLHttpRequest 上传。
    iframe通过 <iframe> 上传。
    custom自定义上传过程,通过 prop upload 方法上传。
    iframe-modestringuploader.iframeMode

    指定在 request-mode 的值为 iframe 的模式下,上传成功后的回调方式。可进行全局统一配置

    描述
    postmessage通过 PostMessage 回调。
    callback通过调用 windowcallback-namespace 里的回调函数回调。
    callback-namespacestringuploader.callbackNamespacerequest-mode 的值为 'iframe' 并且 iframe-mode 的值为 'callback' 的模式下,指定回调函数的命名空间,放在 window 对象下。可进行全局统一配置
    data-typestring'json'

    如果回调的值是文本, 指明文本的解析方式。如果回调的数据是 Object,则 data-type 可以为空。

    描述
    json回调的文本是 JSON。
    text回调的文本是普通文本。
    convert-responseuploader.convertResponse-

    将回调数据转换成需要的格式的函数,使组件能够判断上传是否成功以便显示相应结果,参数是回调数据。返回结果的格式要求如下:

    字段类型描述
    successboolean表示上传是否成功。
    namestring=文件的名称。successtrue 时必须。
    srcstring=文件的地址。successtrue 时必须。
    messagestring=上传失败时的出错信息。successfalse 时必须。
    previewboolean=上传失败时,是否预览失败的上传项。

    还可以给返回结果加上其它自定义的属性,这些自定义属性会被包含在 value 以及 changesuccessfailureremoveprogress 事件的回调参数 file 中 。可进行全局统一配置

    acceptstring-与原生 <input> 元素 的 accept 属性相同,在浏览器的文件类型筛选后再加一层校验。对于类似 application/msword 这样的 MIME type 与扩展名对不上的情形跳过校验。
    max-countnumber-最大文件数量。
    max-sizenumber | string-单个文件的最大大小,如果是 number,单位是 byte;如果是 string,支持在数字后面添加单位,单位可以是 b / kb / mb / gb / tb
    validatorfunction(Object): Object | Promise<Object>-

    自定义校验逻辑,参数为原生 File 对象。返回结果的格式要求如下:

    字段类型描述
    validboolean是否通过校验。
    messagestring=validfalse 时的错误提示信息。
    previewboolean当校验失败时,是否预览失败的上传项。

    支持异步校验,返回值可以是一个 resolve 上述返回结果的 Promise

    payloadObject-附带在上传请求中的额外参数。
    autouploadbooleantrue指定是否在选完文件后立刻上传。
    orderstring'asc'

    上传文件的显示顺序,按照开始上传的时间排序。

    描述
    asc升序排列。
    desc降序排列。
    picker-positionstring'after'

    图片上传模式下,上传按钮在图片队列中的位置。

    描述
    before上传按钮始终在队列最前面。
    after上传按钮始终在队列最后面。
    top上传按钮始终在队列上面。
    none不展示上传按钮。
    uploadfunction(Object, Object): function-

    request-mode 的值是 'custom' 的情况下自定义上传过程,第一个参数为原生 File 对象,第二个参数为包含与上传过程相关的回调函数的对象,具体字段如下:

    字段类型描述
    onloadfunction上传完成的回调函数,参数内容与 convert-response 属性返回值相同。
    onprogressfunction上传进度发生变化的回调函数,参数为 { loaded: number, total: number }loaded 为已上传部分字节数,total 为文件总字节数。
    oncancelfunction自定义上传主动取消时对组件进行的回调,无参数。
    onerrorfunction上传出错的回调函数,参数为 { message: string }message 为错误提示信息。

    如果 upload 返回一个函数,该函数将在用户操作取消或上传组件销毁时被调用,用来中断自定义上传过程。

    controlsfunction(Object, Array<Object>): Array<Object>-

    图片上传模式下,用来自定义配置图片遮罩浮层上的操作项,参数为 (file: Object, defaultControls: Array<Object>)file 为文件相关信息,defaultControls 为包含默认的操作项的数组。可根据文件状态的不同,返回包含不同的操作项的数组。每个操作项的具体字段如下:

    字段类型描述
    namestring操作项的名称,点击该按钮后会抛出同名的事件,事件的回调参数为 (file: Object, index: number)file 为触发事件的文件对象,index 为文件在列表中的序号。
    labelstring操作项的文字描述。
    iconstring操作项使用的图标。
    disabledboolean=操作项是否被禁用。如果该字段为空,则该操作项的禁用状态跟随组件整体的禁用状态。
    multiplebooleanfalse上传多个文件,当 max-count1multipletrue,那么 value 也是数组。
    entriesfunction(Array<Object>): Array<Object>-

    控制每个上传文件的操作项,如删除,预览等,会传递默认的操作项数组作为参数,返回实际生效的操作项数组。操作项对象参考 controls 属性的字段详情。

    pickfunction({remainingCount: number}): Promise<Object>-

    自定义选择文件逻辑, 返回的文件会被上传。

    function pick({ remainingCount: number }): Promise<PickedFile | PickedFile[]>
    
    type PickedFile = {
      name: string
      type: string
      src: string
      poster?: string
      alt?: string
      size?: number
    }
    
    描述
    name文件名称。
    type文件类型。
    src文件地址。
    poster视频文件的预览图片。
    alt替换文本。
    size文件大小。
    after-pickfunction(Array<Object>): void-选择文件之后的回调。
    sortablebooleanfalse文件列表是否可以排序。
    preview-optionsobject{wrap: true, indicator: 'number'}传递给 Lightbox 的预览选项。
    preview-optionsobject{wrap: true, indicator: 'number'}传递给 Lightbox 的预览选项。
    validity-display'popup' | 'inline''popup'

    校验信息的展示方式。

    描述
    popup悬浮时浮层展示校验信息。
    inline内联显示校验信息。
    helpstring-帮助文本。
    help-position'side' | 'bottom''side'

    帮助信息的展示位置。

    描述
    side展示在上传按钮的侧面。
    bottom展示在上传按钮的下面。
    picker-labelstring-上传按钮的文本。
    picker-iconstring | Object-上传按钮的图标,参考 Iconname 属性。

    插槽

    名称描述
    upload图片上传模式下,上传按钮的区域。
    help对文件数量、格式、大小等的提示内容。
    file

    单个文件的区域,用来定制文件内容。

    名称类型描述
    namestring文件的名称。
    srcstring文件的地址。
    statusstring文件的状态。'success' 表示上传成功;'uploading' 表示正在上传;'failure' 表示上传失败。
    indexnumber文件在列表中的序号。
    file-before单个文件内容之前的区域。作用域参数与 file 插槽相同。
    file-after单个文件内容之后的区域。作用域参数与 file 插槽相同。
    uploading图片上传模式下,上传中的单个图片的区域。作用域参数与 file 插槽相同。
    failure图片上传模式下,上传失败的单个图片的区域。作用域参数与 file 插槽相同。

    事件

    名称描述
    change

    只在上传成功、删除文件时触发,回调参数为 (value)

    名称类型描述
    valueObject | Array<Object>组件的 value 的值。
    remove

    删除文件时触发,回调参数为 (file, index)

    名称类型描述
    fileObject被删除的文件。
    indexnumber被删除的文件的序号。

    file 字段详情

    字段类型描述
    namestring文件名称。
    srcstring文件地址。
    statusstring上传状态。'success' 表示上传成功;'uploading' 表示正在上传;'failure' 表示上传失败。

    同时也包含在 convert-response 中添加的自定义属性。

    success上传成功时触发,回调参数与 remove 事件的回调参数相同。
    failure上传失败时触发,回调参数与 remove 事件的回调参数相同。
    invalid

    文件校验失败时触发,回调参数为 (validity: Object)

    名称类型描述
    fileObject没有通过校验的文件信息,与 remove 事件的回调参数中的 file 相同。如果校验失败的原因是选择的文件数量超过最大数量 max-count 限制,则这个字段为空。
    errorsArray<Object>包含该文件所有校验错误信息的数组,数组的每一项是包含校验失败信息的对象。
    名称类型描述
    typestring校验失败的类型,类型枚举值可从 Uploader.errors 对象获取,如 Uploader.errors.SIZE_INVALID
    valuenumber | string | Object没有通过校验的值,根据 type 的不同有不同的类型。
    messagestring检验失败的提示信息。
    类型描述value 类型value 描述
    TYPE_INVALID文件类型校验失败。string文件名称。
    SIZE_INVALID文件大小校验失败。number文件大小字节数。
    TOO_MANY_FILES选择的文件数超过 max-count 限制。number已选择的文件数。
    CUSTOM_INVALIDvalidator 自定义校验失败。Object文件对象,字段同 remove 事件回调参数。
    statuschange

    在所有文件总的状态发生变化时触发,回调参数为组件整体的状态 (status: string)

    描述
    empty没有选择任何文件上传。
    uploading有任一文件正在上传中。
    failure有任一文件上传失败。
    success所有文件上传成功。
    progress

    request-mode 的值为 'xhr' 的情况下,在上传进度发生变化时触发,回调参数为 (file, index, event)

    名称类型描述
    fileObjectremove 事件的回调参数中的 file 相同。
    indexnumber正在上传的文件的序号。
    eventEvent上传进度原生事件。

    全局配置

    名称类型默认值描述
    uploader.requestModestring'xhr'参见 request-mode 属性。
    uploader.iframeModestring'postmessage'参见 iframe-mode 属性。
    uploader.callbackNamespacestring'veuiUploadResult'参见 callback-namespace 属性。
    uploader.headersObject-参见 headers 属性。
    uploader.convertResponsefunction(Object): Object-参见 convert-response 属性。
    uploader.pickerPositionstring'after'参见 picker-position 属性。

    图标

    名称描述
    upload上传文件。
    add-image上传图片。
    clear删除。
    success上传成功。
    failure上传失败。
    loading上传中。
    file已上传文件。
    alert校验失败警告。
    preview预览图片。
    在 GitHub 上编辑此页面编辑