# uni.chooseMedia(options)

拍摄或从手机相册中选择图片或视频。

# chooseMedia 兼容性

Web 微信小程序 Android iOS
x 4.41 4.51 4.51

# 参数

名称 类型 必填 默认值 兼容性 描述
options ChooseMediaOptions - - -
名称 类型 必备 默认值 兼容性 描述
pageOrientation string -
屏幕方向。默认为page.json中的pageOrientation。
合法值 兼容性 描述
auto - 自动
portrait - 竖屏显示
landscape - 横屏显示
count number 9
最多可以选择的文件个数
mediaType Array<string> ['image', 'video']
album 从相册选视频,camera 使用相机拍摄,合法值:'image'、'video'、'mix'
sourceType Array<string> ['album', 'camera']
album 从相册选视频,camera 使用相机拍摄
maxDuration number 10
拍摄视频最长拍摄时间,单位秒。时间范围为 3s 至 30s 之间
camera string -
仅在 sourceType 为 camera 时生效,使用前置或后置摄像头
合法值 兼容性 描述
front - 前置摄像头
back - 后置摄像头
success (callback: ChooseMediaSuccess) => void -
接口调用成功,返回视频文件的临时文件路径,详见返回参数说明
fail (callback: IChooseMediaError) => void -
接口调用失败的回调函数
complete (callback: any) => void -
接口调用结束的回调函数(调用成功、失败都会执行)
sizeType Array<string> -
是否压缩所选文件,基础库2.25.0前仅对 mediaType 为 image 时有效,2.25.0及以后对全量 mediaType 有效

# ChooseMediaSuccess 的属性值

名称 类型 必备 默认值 兼容性 描述
tempFiles Array<ChooseMediaTempFile> - - -
名称 类型 必备 默认值 兼容性 描述
tempFilePath string - - 选定视频的临时文件路径
fileType string - - 文件类型
合法值 兼容性 描述
image - -
video - -
size number - - 选定视频的数据量大小
duration number - - 选定视频的时间长度
height number - - 返回选定视频的长
width number - - 返回选定视频的宽
thumbTempFilePath string - - 视频缩略图临时文件路径
type string - - -
合法值 兼容性 描述
image - -
video - -
mix - -

# IChooseMediaError 的属性值

名称 类型 必备 默认值 兼容性 描述
errCode number - - 错误码
合法值 兼容性 描述
1101001 - 用户取消
1101005 - 未获取权限
1101006 - 图片或视频保存失败
1101008 - 拍照或录像失败
errSubject string - - 统一错误主题(模块)名称
data any - - 错误信息中包含的数据
cause Error - - 源错误信息,可以包含多个错误,详见SourceError
errMsg string - - -

# 参见

# 示例

hello uni-app x

该 API 不支持 Web,请运行 hello uni-app x 到 App 平台体验

扫码体验(手机浏览器跳转到App直达页)
<template>
  <!-- #ifdef APP -->
  <scroll-view class="page-scroll-view">
  <!-- #endif -->
    <view>
      <page-head :title="title"></page-head>
      <view class="uni-common-mt">
        <view class="uni-list">

          <view class="uni-list-cell cell-pd">
            <view class="uni-list-cell-left uni-label">
              来源
            </view>
            <view class="uni-list-cell-right" @click="chooseMediaSource">
              <text class="click-t">{{sourceTypes[sourceTypeIndex].title}}</text>
            </view>
          </view>

          <view class="uni-list-cell cell-pd">
            <view class="uni-list-cell-left uni-label">
              方式
            </view>
            <view class="uni-list-cell-right" @click="chooseMediaType">
              <text class="click-t">{{(mediaTypes[mediaTypeIndex] as ChooseSource).title}}</text>
            </view>
          </view>

          <view class="uni-list-cell cell-pd">
            <view class="uni-list-cell-left uni-label">
              数量限制
            </view>
            <view class="uni-list-cell-right">
              <input class="click-t" ref="refCountInput" :value="countIndex" type="number" :maxlength="1" @confirm="chooseMediaCount" confirm-type="done" />
            </view>
          </view>

          <!-- #ifdef APP-ANDROID -->
          <view class="uni-list-cell cell-pd">
            <view class="uni-list-cell-left uni-label">
              屏幕方向
            </view>
            <view class="uni-list-cell-right" @click="chooseOrientationType">
              <text class="click-t">{{orientationTypes[orientationTypeIndex].title}}</text>
            </view>
          </view>
          <!-- #endif -->

          <view class="uni-list-cell cell-pd">
            <view class="uni-list-cell-left uni-label">
              摄像头
            </view>
            <view class="uni-list-cell-right" @click="chooseCameraType">
              <text class="click-t">{{cameraTypes[cameraTypeIndex].title}}</text>
            </view>
          </view>
        </view>
        <!-- #ifdef APP-IOS -->
        <input-data title="最长拍摄时间,单位秒" defaultValue="10" type="number" @confirm="onMaxDurationConfirm"></input-data>
        <!-- #endif -->
        <view class="uni-list list-pd" style="padding: 15px;">
          <view class="uni-flex" style="margin-bottom: 10px;">
            <view class="uni-list-cell-left">点击预览</view>
            <view style="margin-left: auto;">
              <text class="click-t">{{mediaList.length}}/{{countIndex}}</text>
            </view>
          </view>
          <view class="uni-flex" style="flex-wrap: wrap;">
            <view v-for="(file,index) in mediaList" :key="index" class="uni-uploader__input-box" style="border: 0;">
              <image style="width: 104px; height: 104px;" :src="file.imagePath" :data-src="file.imagePath" @tap="previewMedia(index)">
              </image>
              <image src="/static/plus.png" class="image-remove" @click="removeMedia(index)"></image>
            </view>
            <image class="uni-uploader__input-box" @tap="chooseMedia" src="/static/plus.png"></image>
          </view>
        </view>
      </view>
    </view>
  <!-- #ifdef APP -->
  </scroll-view>
  <!-- #endif -->
</template>

<script>
  type FileSource = {
    imagePath : string;
    filePath : string;
    fileType : string;
  };
  type ChooseSource = {
    value : string[];
    title : string;
  };
  const sourceTypeList : ChooseSource[] = [
    {
      value: ['camera'],
      title: '拍摄',
    },
    {
      value: ['album'],
      title: '相册',
    },
    {
      value: ['camera', 'album'],
      title: '拍摄或相册',
    }
  ];

  const mediaTypeList : ChooseSource[] = [
    {
      value: ['image'],
      title: '仅图片',
    },
    {
      value: ['video'],
      title: '仅视频',
    },
    {
      value: ['image', 'video'],
      title: '不限制',
    }
  ];

  const orientationTypeList : ChooseSource[] = [
    {
      value: ['portrait'],
      title: '竖屏',
    },
    {
      value: ['landscape'],
      title: '横屏',
    },
    {
      value: ['auto'],
      title: '自动',
    }
  ];
  const cameraTypeList : ChooseSource[] = [
    {
      value: ['front'],
      title: '前置摄像头',
    },
    {
      value: ['back'],
      title: '后置摄像头',
    }
  ];
  export default {
    data() {
      return {
        title: 'chooseMedia',
        mediaList: [] as Array<FileSource>,
        sourceTypeIndex: 2,
        mediaTypeIndex: 2,
        cameraTypeIndex: 1,
        orientationTypeIndex: 0,
        albumModeTypeIndex: 0,
        countIndex: 9,
        maxDuration: 10,
        sourceTypes: sourceTypeList as ChooseSource[],
        mediaTypes: mediaTypeList as ChooseSource[],
        cameraTypes: cameraTypeList as ChooseSource[],
        orientationTypes: orientationTypeList as ChooseSource[]
      }
    },
    methods: {
      chooseMediaSource() {
        uni.showActionSheet({
          itemList: ['拍摄', '相册', '拍摄或相册'],
          success: (e) => {
            this.sourceTypeIndex = e.tapIndex
          }
        })
      },
      chooseMediaType() {
        uni.showActionSheet({
          itemList: ['仅图片', '仅视频', '不限制'],
          success: (e) => {
            this.mediaTypeIndex = e.tapIndex
          }
        })
      },
      chooseMediaCount(event : UniInputConfirmEvent) {
        let count = parseInt(event.detail.value)
        if (count < 1 || count > 9 || Number.isNaN(count)) {
          uni.showToast({
            position: "bottom",
            title: "图片数量应该不小于1不大于9"
          })
          this.countIndex = 9;
          return
        }
        this.countIndex = count
      },
      chooseOrientationType() {
        uni.showActionSheet({
          itemList: ['竖屏', '横屏', '自动'],
          success: (e) => {
            this.orientationTypeIndex = e.tapIndex
          }
        })
      },
      chooseCameraType() {
        uni.showActionSheet({
          itemList: ['前置', '后置'],
          success: (e) => {
            this.cameraTypeIndex = e.tapIndex
          }
        })
      },
      onMaxDurationConfirm(value : number) {
        this.maxDuration = value;
      },
      chooseMedia() {
        if (this.mediaList.length >= this.countIndex) {
          const message = "已经有" + this.countIndex + "个了,请删除部分后重新选择";
          uni.showToast({
            position: "bottom",
            title: message
          })
          return
        }

        uni.chooseMedia({
          count: this.mediaList.length + this.countIndex > 9 ? 9 - this.mediaList.length : this.countIndex,
          sourceType: sourceTypeList[this.sourceTypeIndex].value,
          mediaType: mediaTypeList[this.mediaTypeIndex].value,
          camera: cameraTypeList[this.cameraTypeIndex].value[0],
          // #ifdef APP-IOS
          maxDuration: this.maxDuration,
          // #endif
          // #ifdef APP-ANDROID
          pageOrientation: orientationTypeList[this.orientationTypeIndex].value[0],
          // #endif
          success: (res) => {
            const tempFiles : ChooseMediaTempFile[] = res.tempFiles as ChooseMediaTempFile[];
            for (let i = 0; i < tempFiles.length; i++) {
              const tempFile : ChooseMediaTempFile = tempFiles[i]
              const imagePath = tempFile.fileType == "image" ? tempFile.tempFilePath : tempFile.thumbTempFilePath;
              const file : FileSource = { imagePath: imagePath!, filePath: tempFile.tempFilePath, fileType: tempFile.fileType };
              this.mediaList.push(file);
            }
          },
          fail: (err) => {
            console.log("err: ", JSON.stringify(err));
          }
        })
      },
      previewMedia: function (index : number) {
        const file : FileSource = this.mediaList[index];
        if (file.fileType == "image") {
          uni.previewImage({
            current: 0,
            urls: [file.filePath]
          })
        } else {
          uni.$once("__ONFULLVIDEOLOAD", () => {
            uni.$emit("__ONRECEIVEURL", {
              "url": file.filePath,
              "cover": file.imagePath
            })
          })
          const url = "/pages/API/choose-media/fullscreen-video";
          uni.navigateTo({
            url: url,
          })
        }

      },
      removeMedia(index : number) {
        this.mediaList.splice(index, 1)
      },
    }
  }
</script>

<style>
  .cell-pd {
    padding: 11px 15px;
  }

  .click-t {
    color: darkgray;
  }

  .list-pd {
    margin-top: 25px;
  }

  .uni-uploader__input-box {
    margin: 5px;
    width: 104px;
    height: 104px;
    border: 1px solid #D9D9D9;
  }

  .uni-uploader__input {
    position: absolute;
    z-index: 1;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
  }

  .image-remove {
    transform: rotate(45deg);
    width: 25px;
    height: 25px;
    position: absolute;
    top: 0;
    right: 0;
    border-radius: 13px;
    background-color: rgba(200, 200, 200, 0.8);
  }

  .item_width {
    width: 130px;
  }
</style>

# 通用类型

# GeneralCallbackResult

名称 类型 必备 默认值 兼容性 描述
errMsg string -
错误信息

# Tips

  • chooseMedia的相册选择在App平台是系统UI,其风格不同rom可能有差异。多选时有的是长按、有的是checkbox。系统UI的暗黑模式、国际化跟随系统,而不跟随App。