适用场景与兼容性
在鸿蒙端使用 uni-app x 开发应用时,头像、商品图片、视频和文档附件都需要有存储位置。原文给出的方案是直接使用 uniCloud 云存储,避免自建文件服务器;其中 uploadFile、chooseAndUploadFile、getTempFileURL 三个核心 API 在鸿蒙 4.61 全部支持。需要特别留意版本差异:4.18 之前 uni-app-x 在 app 端仅支持选择图片,type 只能设为 image;4.18 及之后的版本才支持图片和视频,type 可设为 image 或 video。
三个 API 的职责划分
uploadFile 用于把本地文件上传到云存储,核心参数是 filePath、cloudPath 和 onUploadProgress,成功后可拿到 fileID。chooseAndUploadFile 把选择文件和上传合并,支持 type、sourceType、count、sizeType、maxDuration、camera 等配置;onChooseFile 在选完文件后回调,onUploadProgress 返回上传进度,结果中的 tempFiles 可继续取 name、path、cloudPath、url 等信息。getTempFileURL 则根据 fileID 换取临时访问链接,入参是 fileList,返回结果的 fileList 中每项包含 fileID 和 tempFileURL。
上传本地文件与进度处理
上传前通常先用时间戳和扩展名生成云端唯一路径 cloudPath,再调用 uploadFile。原文示例在上传期间用 showLoading 提示,并通过 progress.loaded 与 progress.total 计算百分比;成功后拿 res.fileID,失败后在 catch 中隐藏 loading 并提示上传失败。- const uploadLocalFile = (filePath: string) => {
- const timestamp = Date.now()
- const ext = filePath.split('.').pop() || 'jpg'
- const cloudPath = 'uploads/' + timestamp + '.' + ext
- uni.showLoading({ title: '上传中...' })
- uniCloud.uploadFile({
- filePath: filePath,
- cloudPath: cloudPath,
- onUploadProgress: (progress) => {
- const percent = Math.floor((progress.loaded / progress.total) * 100)
- console.log('上传进度:', percent + '%')
- }
- }).then((res) => {
- uni.hideLoading()
- console.log('上传成功,fileID:', res.fileID)
- uni.showToast({ title: '上传成功', icon: 'success' })
- }).catch((err) => {
- uni.hideLoading()
- console.error('上传失败:', err)
- uni.showToast({ title: '上传失败', icon: 'none' })
- })
- }
复制代码
选择图片、视频并上传
如果希望用户先选择再自动上传,可使用 chooseAndUploadFile。图片场景可设置 type 为 image,sourceType 为 album 和 camera,count 为 1,sizeType 为 compressed;视频场景可设置 type 为 video,sourceType 为 album 和 camera,maxDuration 为 60,camera 为 back。注意视频选择要建立在 4.18 及之后版本的兼容性前提上。选择完成后,res.tempFiles[0] 可读取 name、cloudPath、url 等结果。- uniCloud.chooseAndUploadFile({
- type: 'image',
- sourceType: ['album', 'camera'],
- count: 1,
- sizeType: ['compressed'],
- onChooseFile: (res) => {
- console.log('选择的文件:', res.tempFiles[0].name)
- },
- onUploadProgress: (progress) => {
- const percent = Math.floor((progress.loaded / progress.total) * 100)
- console.log('上传进度:', percent + '%')
- }
- }).then((res) => {
- const file = res.tempFiles[0]
- console.log('上传成功,fileID:', file.cloudPath)
- console.log('访问链接:', file.url)
- uni.showToast({ title: '上传成功', icon: 'success' })
- }).catch((err) => {
- console.error('失败:', err)
- uni.showToast({ title: '上传失败', icon: 'none' })
- })
复制代码
批量上传与临时链接获取
批量上传图片时,原文使用 type 为 image、sourceType 为 album、count 为 9、sizeType 为 compressed;进度回调中的 progress.index 可用于判断当前是第几张。上传结束后遍历 res.tempFiles 即可拿到每张图片的 url。获取临时链接时,单文件和批量都走 getTempFileURL,只需传入 fileList,返回后遍历 res.fileList,其中 item.fileID 对应原文件,item.tempFileURL 就是临时访问地址。- uniCloud.getTempFileURL({
- fileList: ['cloud://xxx/images/avatar.jpg']
- }).then((res) => {
- res.fileList.forEach((item) => {
- console.log('fileID:', item.fileID)
- console.log('临时链接:', item.tempFileURL)
- })
- }).catch((err) => {
- console.error('获取链接失败:', err)
- })
复制代码
上传后保存 fileID 到数据库
文件上传成功只是第一步,业务数据通常还要记录文件归属。原文示例先上传文件,再用 uniCloud.databaseForJQL() 获取数据库实例,向 files 集合 add 一条记录,保存 fileID、cloudPath、originalName 和 uploadTime,并给 add 参数加上 as UTSJSONObject。这样后续可以根据业务记录中的 fileID 再调用 getTempFileURL 换取临时链接。- const uploadAndSave = (filePath: string) => {
- const timestamp = Date.now()
- const ext = filePath.split('.').pop() || 'jpg'
- const cloudPath = 'images/' + timestamp + '.' + ext
- uni.showLoading({ title: '上传中...' })
- uniCloud.uploadFile({
- filePath: filePath,
- cloudPath: cloudPath
- }).then((res) => {
- const db = uniCloud.databaseForJQL()
- return db.collection('files').add({
- fileID: res.fileID,
- cloudPath: cloudPath,
- originalName: filePath.split('/').pop(),
- uploadTime: Date.now()
- } as UTSJSONObject)
- }).then((res) => {
- uni.hideLoading()
- console.log('上传并保存成功')
- uni.showToast({ title: '上传成功', icon: 'success' })
- }).catch((err) => {
- uni.hideLoading()
- console.error('上传或保存失败:', err)
- uni.showToast({ title: '上传失败', icon: 'none' })
- })
- }
复制代码
页面落地与排障思路
原文的完整页面使用 template 加 script setup lang="uts",维护 inputFileID、uploadProgress、uploadedFiles、tempURL 等状态,并提供上传图片、上传视频、批量上传图片、获取临时链接几个按钮。上传进度在页面中用进度条展示,上传结果与临时链接结果分块展示。排障时重点检查三类问题:一是 chooseAndUploadFile 的 type 是否与当前 uni-app-x 版本匹配,4.18 之前不要使用 video;二是上传失败是否在 catch 中正确 hideLoading 并提示;三是 getTempFileURL 前 fileID 不能为空,原文在输入为空时会直接 toast 提示请输入 fileID。
实践结论
对于鸿蒙端 uni-app x 项目,uniCloud 云存储的 uploadFile、chooseAndUploadFile、getTempFileURL 已经覆盖了上传、选择上传和临时链接换取三个关键环节。落地时把 cloudPath 唯一性、进度回调、4.18 版本兼容和 fileID 落库处理好,就可以用较少代码完成文件存储闭环;原文也明确说明,这比自己搭 OSS 简单太多。 |