uni-app 跨平台图片选择指南:uni.chooseImage 参数详解、相册模式与源码实现剖析
2026/9/20 20:06:02 网站建设 项目流程

uni-app 跨平台图片选择指南:uni.chooseImage 参数详解、相册模式与源码实现剖析

【免费下载链接】uni-appA cross-platform framework using Vue.js项目地址: https://gitcode.com/gh_mirrors/un/uni-app

本文基于 uni-app 官方文档 docs/api/choose-image.md 与仓库内uni-media模块的跨端实现,系统讲解uni.chooseImage从相册选图、调用相机拍照、图片压缩与裁剪的完整能力。读完本文,你将掌握该 API 的每一个参数与回调字段、App 端 custom/system 两种相册选择模式的差异与权限模型、完整的错误码体系,并能从源码层面理解各平台(Android / iOS / HarmonyOS / Web / 微信小程序)的底层行为差异。

一、API 概览与兼容性

uni.chooseImage(options)用于从本地相册选择图片或使用相机拍照,是 uni-app 中最常用的媒体能力之一。它以ChooseImageOptions作为唯一入参,成功时通过回调返回图片的本地文件路径列表tempFilePaths

从仓库中uni-media模块的类型定义(interface.uts)可以看到,其完整签名是:

export type ChooseImage = (options: ChooseImageOptions) => void

平台兼容性

| Web | 微信小程序 | Android | iOS | HarmonyOS | | :- | :- | :- | :- | :- | | 4.0 | 4.41 | 3.9 | 4.11 | 4.61 |

说明:上表版本号指 uni-app x(HBuilderX 的 uni-app x 编译器)版本,兼容性标注以本文档为准。需要特别注意的是,sizeType在 HarmonyOS 端对应版本为 4.61(uni-app x 4.23 起)。

二、options 参数详解

options为必填项,类型为ChooseImageOptions。下表完整列出其全部属性:

| 名称 | 类型 | 必备 | 默认值 | 兼容性 | 描述 | | :- | :- | :- | :- | :-: | :- | | pageOrientation | string | 否 | (见下) | Web: x; 微信小程序: x; Android: 4.33; iOS: 4.33; HarmonyOS: x | 屏幕方向。默认为 pages.json 中的 pageOrientation。 | | albumMode | string | 否 | "custom" | Web: x; 微信小程序: x; Android: 4.33; iOS: x; HarmonyOS: x | 图片选择模式 | | count | number | 否 | 9 | 微信小程序: 4.41; Android: 3.9; iOS: 4.11 | 最多可以选择的图片张数,app 端不限制,微信小程序最多可支持 20 个。 | | sizeType | Array<string> | 否 | ['original','compressed'] | Web: x; 微信小程序: 4.41; Android: 3.9; iOS: 4.11; HarmonyOS: 4.61 | original 原图,compressed 压缩图,默认二者都有 | | sourceType | Array<string> | 否 | ['album','camera'] | 微信小程序: 4.41; Android: 3.9; iOS: 4.11 | album 从相册选图,camera 使用相机,默认二者都有 | | extension | Array<string> | 否 | (默认不过滤) | Web: 4.0; 其余平台: x | 根据文件拓展名过滤,每一项都不能是空字符串。仅 H5 支持 | | crop | ChooseImageCropOptions | 否 | (无) | Web: x; Android: 3.9; iOS: 4.11; HarmonyOS: x | 图像裁剪参数,设置后 sizeType 失效。 | | success | (callback: ChooseImageSuccess) => void | 否 | (无) | 微信小程序: 4.41; Android: 3.9; iOS: 4.11 | 成功则返回图片的本地文件路径列表 tempFilePaths | | fail | (callback: ChooseImageFail) => void | 否 | (无) | 微信小程序: 4.41; Android: 3.9; iOS: 4.11 | 接口调用失败的回调函数 | | complete | (callback: any) => void | 否 | (无) | 微信小程序: 4.41; Android: 3.9; iOS: 4.11 | 接口调用结束的回调函数(调用成功、失败都会执行) |

2.1 pageOrientation(屏幕方向)

可选合法值如下,默认取 pages.json 中的pageOrientation配置:

| 合法值 | 描述 | | :- | :- | | "auto" | 自动 | | portrait | 竖屏显示 | | landscape | 横屏显示 |

在源码中对应类型ChooseImagePageOrientation(interface.uts),其注释进一步明确:该参数仅 App 端(Android/iOS)支持,Web 与微信小程序等平台不支持。

2.2 albumMode(图片选择模式,仅 Android)

| 合法值 | 描述 | | :- | :- | | "custom" | 自定义媒体选择器 | | system | 系统媒体选择器 |

该参数默认值为"custom",仅 Android 端支持(4.33 起),iOS、Web、微信小程序均不支持。custom 与 system 两种模式的差异较大,是 Android 上架与权限合规的关键选择,详见本文第四节。

2.3 count、sizeType、sourceType、extension

  • count:最多可选图片数,默认 9。app 端不限制,微信小程序最多 20 个。
  • sizeType'original'(原图)与'compressed'(压缩图)的组合,默认['original','compressed']二者都提供。
  • sourceType'album'(相册选图)与'camera'(相机拍照)的组合,默认['album','camera']两者都提供。
  • extension:按文件扩展名过滤图片,每一项不能是空字符串,默认不过滤,仅 H5 支持。

从源码 protocol.uts 可以看出这些默认值在框架层是如何落地的:ChooseImageApiOptions.formatArgs中,当countsizeTypesourceType未传入时会分别被规范化为9['original', 'compressed']['album', 'camera']extension未传入时默认置为['*']。也就是说,即使调用方不传任何参数,框架也会在参数预处理阶段补齐一套可用的默认配置。

2.4 crop(图像裁剪,设置后 sizeType 失效)

crop 的类型为ChooseImageCropOptions,属性如下:

| 名称 | 类型 | 必备 | 默认值 | 兼容性 | 描述 | | :- | :- | :- | :- | :- | :- | | width | number | 是 | (必填) | Android: 3.9; iOS: 4.11 | 裁剪的宽度,单位为 px,用于计算裁剪宽高比。 | | height | number | 是 | (必填) | Android: 3.9; iOS: 4.11 | 裁剪的高度,单位为 px,用于计算裁剪宽高比。 | | quality | number | 否 | 80 | Android: 3.9; iOS: 4.11 | 取值范围为 1-100,数值越小,质量越低(仅对 jpg 格式有效)。默认值为 80。 | | resize | boolean | 否 | true | Android: 3.9; iOS: 4.11 | 是否将 width 和 height 作为裁剪保存图片真实的像素值。默认值为 true。注:设置为 false 时在裁剪编辑界面显示图片的像素值,设置为 true 时不显示。 |

从源码实现看(ChooseMediaUtils.uts),Android 端在打开相册选择器时会将 crop 配置序列化为image_crop传入图片选择器 Activity(openGalleryActivity中的albumIntent.putExtra("image_crop", JSON.stringify(crop))),并在进入裁剪编辑时限制只能选中一张图(max_select_count被置为 1);拍照场景下同样会携带IMAGE_CROP进入图片编辑 Activity 完成裁切。这印证了文档中"设置 crop 后 sizeType 失效"的语义——裁剪输出由 crop 的 width/height/quality 决定,不再走原有的压缩流程。

三、回调返回值详解

3.1 ChooseImageSuccess(成功回调)

| 名称 | 类型 | 必备 | 兼容性 | 描述 | | :- | :- | :- | :-: | :- | | errSubject | string | 是 | Android: 3.9; iOS: 4.11 | 调用 API 的名称 | | errMsg | string | 是 | Android: 3.9; iOS: 4.11 | 描述信息 | | tempFilePaths | Array<string> | 是 | 微信小程序: 4.41; Android: 3.9; iOS: 4.11 | 图片的本地文件路径列表 | | tempFiles | Array<ChooseImageTempFile> | 是 | 微信小程序: 4.41; Android: 3.9; iOS: 4.11 | 图片的本地文件列表 |

其中tempFiles每个元素的属性:

| 名称 | 类型 | 必备 | 兼容性 | 描述 | | :- | :- | :- | :-: | :- | | path | string | 是 | Android: 3.9; iOS: 4.11 | 本地文件路径 | | size | number | 是 | Android: 3.9; iOS: 4.11 | 本地文件大小,单位:B | | name | string | 否 | Android: x; iOS: x | 包含扩展名的文件名称,仅 H5 支持 | | type | string | 否 | Android: x; iOS: x | 文件类型,仅 H5 支持 |

源码中ChooseImageTempFile(interface.uts)的字段与文档一一对应,且nametype均标注为"仅 H5 支持",App 端返回 null。

3.2 ChooseImageFail(失败回调)

| 名称 | 类型 | 必备 | 描述 | | :- | :- | :- | :- | | errCode | number | 是 | 错误码 | | errSubject | string | 是 | 统一错误主题(模块)名称 | | data | any | 否 | 错误信息中包含的数据 | | cause | Error | 否 | 源错误信息,可以包含多个错误,详见 SourceError | | errMsg | string | 是 | 错误描述 |

四、错误码体系(errCode)

uni.chooseImage及整个媒体模块共用一套错误码,定义于 unierror.uts 的MediaUniErrors映射表中:

| 错误码 | 描述 | 英文信息(源码) | | :- | :- | :- | | 1101001 | 用户取消 | user cancel | | 1101002 | urls 至少包含一张图片地址 | fail parameter error: parameter.urls should have at least 1 item | | 1101003 | 文件不存在 | file not find | | 1101004 | 图片加载失败 | Failed to load resource | | 1101005 | 未获取权限 | No Permission | | 1101006 | 图片或视频保存失败 | save error | | 1101007 | 图片裁剪失败 | crop error | | 1101008 | 拍照或录像失败 | camera error | | 1101009 | 图片压缩失败 | image output failed | | 1101010 | 其他错误 | unexpect error: |

错误对象通过MediaErrorImpl构造,错误主题为uni-chooseImage(源码中UniError_ChooseImage = "uni-chooseImage")。例如在 Android 端,用户取消选择时触发1101001,权限被拒绝时触发1101005,拍照文件不存在时触发1101008,图片裁切失败时触发1101007——这些错误码在 ChooseMediaUtils.uts 的相机、相册、裁剪各分支中均有对应实现。

五、完整可运行示例

官方示例位于仓库演示工程 src/pages/API/choose-image/choose-image.uvue,覆盖了 sourceType、sizeType、count、pageOrientation、albumMode、crop 全部参数的交互式配置。核心调用逻辑如下(Uts 语法,<script setup lang="uts">):

const chooseImage = () => { if (imageList.value.length >= count.value) { uni.showToast({ position: "bottom", title: `已经有 ${count.value} 张图片了,请删除部分图片之后重新选择` }) return } uni.chooseImage({ sourceType: sourceTypeArray[sourceTypeIndex.value], // ['camera'] / ['album'] / ['camera','album'] sizeType: sizeTypeArray[sizeTypeIndex.value], // ['compressed'] / ['original'] / ['compressed','original'] crop: isCrop.value ? { "quality": cropPercent.value, "width": cropWidth.value, "height": cropHeight.value, "resize": cropResize.value } as ChooseImageCropOptions : null, count: count.value - imageList.value.length, // #ifdef APP pageOrientation: orientationTypeArray[orientationTypeIndex.value], // portrait / landscape / auto // #endif // #ifdef APP-ANDROID albumMode: albumModeTypeArray[albumModeTypeIndex.value], // custom / system // #endif success: (res) => { imageList.value = imageList.value.concat(res.tempFilePaths); }, fail: (err) => { uni.showToast({ title: "choose image error.code:" + err.errCode + ";message:" + err.errMsg, position: "bottom" }) } }) }

示例页面配合uni.previewImage实现选图后的预览,配合uni.showActionSheet切换图片来源/质量/屏幕方向等选项。仓库中还有对应的自动化测试用例 choose-image.test.js,用于验证页面正常渲染与截图快照。

示例中的几个工程要点值得注意:

  1. 条件编译的使用pageOrientation#ifdef APP限定 App 端传入,albumMode#ifdef APP-ANDROID限定 Android 端传入,与文档兼容性矩阵完全一致。
  2. 数量自校验:选择前先判断已选图片数量是否达到上限,避免超选。
  3. 裁剪参数组装:启用裁剪时以as ChooseImageCropOptions显式断言类型,quality 输入范围校验为 0~100。

六、App 端相册选择的 2 种方式:custom 与 system

App 平台的相册选择存在custom(自定义)与system(系统)两种模式,二者差异显著,直接影响权限申请、Google Play 上架合规、UI 定制能力与临时文件生成行为。

6.1 custom 方式(自定义媒体选择器)

  1. 权限模型:app 需要读取相册文件,因此必须申请相册/本地文件访问权限。而 Google Play 目前仅对合理需要相册权限的应用开放相册权限;若无法向 Google 证明获取相册权限的合理性,则应改用 system 方式。使用 custom 方式上架 Google Play 时需要提交声明以获得试用资格。uni-app x 开发者可升级 HBuilderX 4.41 后改用 system 方式,而 uni-app(非 x)开发者可借助插件方案解决该问题。
  2. 支持"原图"选项:custom 选择器可让用户选择原图。
  3. 临时文件:使用非原图(即压缩图片)时,会在应用沙盒目录的 cache 目录产生临时文件(压缩后的图片),位置详见 file-system-spec.md#cache。
  4. 4.41 起的行为变化:在 4.41 以前,Android 无论如何都会在应用沙盒 cache 目录产生临时文件;从 4.41 起,chooseImage 支持 contentURI,选择照片时如果不压缩图片,会直接返回 contentURI,不再向 cache 目录写临时文件。

从源码可以印证上述第 4 点:ChooseMediaUtils.uts 在组装相册选择结果时,会判断路径前缀path.startsWith("file://") || path.startsWith("content://")并原样保留,这意味着系统照片选择器返回的 content:// URI 会被直接透传给业务层;同一模块的 app-android/index.uts 中也对content://前缀做了分支处理,用于在不落盘的情况下读取与压缩图片。

6.2 system 方式(系统媒体选择器)

  1. 无需额外权限:使用系统选择器时,应用不需要申请额外权限,其模式类似于 Web 浏览器中的input type=file——应用本身不具备本机文件访问能力,由用户通过系统选择器把图片传给应用。

  2. Google Play 上架友好:system 方式无需向 Google 特别声明选择权限的必要性即可正常上架。但注意需要在 manifest.json 中移除以下两个权限:

    • <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
    • <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />

    配置方式参考 Android 原生资源中的"移除 Android 权限"章节(app-nativeresource-android.md)。

  3. UI 无法自定义:如 Android、iOS 上无法添加"原图"选项;鸿蒙上系统 UI 自带原图选项。

  4. 主题与国际化跟随系统:界面 UI 的主题和国际化跟随手机 ROM,而不是跟随 App(即使 App 与 ROM 设置不一致)。

  5. 无临时文件:因为不涉及压缩,所以也没有临时文件,不会在 cache 目录下生成临时文件。

6.3 两种模式的源码实现差异

在 ChooseMediaUtils.uts 的openGalleryActivity中可以看到两者的分派逻辑:

if (useSystem == "system") { albumIntent.setClassName(getUniActivity()!!, "io.dcloud.uts.pick.SystemPickerActivity"); } else { albumIntent.setClassName(getUniActivity()!!, "io.dcloud.uts.dmcbig.mediapicker.PickerActivity"); }

即 system 模式启动的是框架内置的系统选择器 Activity,custom 模式启动的是自定义媒体选择器。权限申请流程也有明显区别(chooseMediaImage):system 模式下,当系统版本高于 Android 12(SDK > 32)或 targetSdkVersion >= 33 时直接打开系统照片选择器,不申请任何权限;而 custom 模式在 targetSdkVersion >= 33 时申请READ_MEDIA_IMAGES,低于 33 时申请READ_EXTERNAL_STORAGE,拍照场景申请CAMERA权限,拒绝后回调1101005

七、HarmonyOS 端实现要点

从 app-harmony/media/chooseImage.uts 可以看到鸿蒙端的实现逻辑:

  • 图片来源分派sourceType['camera']时直接调用_takePhoto;为['album']时通过photoAccessHelperPhotoViewMIMETypes.IMAGE_TYPE)调用系统相册;两者都有时先弹出uni.showActionSheet让用户选择"拍摄 / 从相册选择"。
  • sizeType 的处理:通过options.sizeType判断是否支持原图:仅['original']original = true;同时包含 original 与 compressed 时由系统 UI 提供原图选项。这与文档"鸿蒙上系统 UI 自带原图选项"的描述一致。
  • 临时文件结构:鸿蒙端返回的tempFiles只包含pathsize两个字段,nametype为 null。

八、Tips 与工程实践建议

  1. 权限自动申请:本 API 会自动申请摄像头、相册等相关权限。如需手动获取 app 是否拥有摄像头和相册权限,参考 getAppAuthorizeSetting。
  2. 临时文件清理:app 端拍照和部分情况下的相册选择会在应用沙盒目录的 cache 目录产生临时文件(位置见 file-system-spec.md#cache)。如需主动删除临时文件,使用 getFileSystemManager。
  3. contentURI 返回条件:从 HBuilderX 4.41 版起,uni.chooseImagesourceType['album']albumModesystemsizeType['original']且未设置crop时,支持返回 Uri 地址(content://),此时不会产生临时文件。
  4. albumMode 语义albumModesystem打开的是系统的图片选择器;custom打开的是 uni-app x 框架提供的图片选择器。
  5. 系统选择器的 sizeType 限制:系统图片选择器的sizeType仅支持设置['original']['compressed']。在 Android 11 及以上系统中,设置system调用的是系统的照片选择器;低于 Android 11 的系统会调用系统的文件选择器。
  6. 选择结果消费链路tempFilePaths返回的是本地路径或 content:// URI,可以直接传给<image>组件渲染、uni.previewImage预览,或配合 uploadFile 上传到服务端;如需进一步处理图片(如压缩、获取信息),可参考仓库中 compress-image 与 get-image-info 相关文档。

九、阅读延伸

  • 媒体模块类型定义与平台标注:interface.uts
  • 参数协议与默认值规范化:protocol.uts
  • 错误码与错误对象:unierror.uts
  • Android 端选择器/相机/裁剪实现:ChooseMediaUtils.uts
  • HarmonyOS 端实现:chooseImage.uts
  • 官方交互示例:choose-image.uvue
  • 自动化测试:choose-image.test.js
  • 相关 API:图片预览 preview-image、图片压缩 compress-image、文件系统 file-system-spec、错误规范 err-spec

【免费下载链接】uni-appA cross-platform framework using Vue.js项目地址: https://gitcode.com/gh_mirrors/un/uni-app

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询