查看: 143|回复: 0

鸿蒙 uni-app x 云存储上传与临时链接获取实战

[复制链接]
发表于 1 小时前 | 显示全部楼层 |阅读模式
适用场景与兼容性
在鸿蒙端使用 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 并提示上传失败。
  1. const uploadLocalFile = (filePath: string) => {
  2.   const timestamp = Date.now()
  3.   const ext = filePath.split('.').pop() || 'jpg'
  4.   const cloudPath = 'uploads/' + timestamp + '.' + ext
  5.   uni.showLoading({ title: '上传中...' })
  6.   uniCloud.uploadFile({
  7.     filePath: filePath,
  8.     cloudPath: cloudPath,
  9.     onUploadProgress: (progress) => {
  10.       const percent = Math.floor((progress.loaded / progress.total) * 100)
  11.       console.log('上传进度:', percent + '%')
  12.     }
  13.   }).then((res) => {
  14.     uni.hideLoading()
  15.     console.log('上传成功,fileID:', res.fileID)
  16.     uni.showToast({ title: '上传成功', icon: 'success' })
  17.   }).catch((err) => {
  18.     uni.hideLoading()
  19.     console.error('上传失败:', err)
  20.     uni.showToast({ title: '上传失败', icon: 'none' })
  21.   })
  22. }
复制代码

选择图片、视频并上传
如果希望用户先选择再自动上传,可使用 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 等结果。
  1. uniCloud.chooseAndUploadFile({
  2.   type: 'image',
  3.   sourceType: ['album', 'camera'],
  4.   count: 1,
  5.   sizeType: ['compressed'],
  6.   onChooseFile: (res) => {
  7.     console.log('选择的文件:', res.tempFiles[0].name)
  8.   },
  9.   onUploadProgress: (progress) => {
  10.     const percent = Math.floor((progress.loaded / progress.total) * 100)
  11.     console.log('上传进度:', percent + '%')
  12.   }
  13. }).then((res) => {
  14.   const file = res.tempFiles[0]
  15.   console.log('上传成功,fileID:', file.cloudPath)
  16.   console.log('访问链接:', file.url)
  17.   uni.showToast({ title: '上传成功', icon: 'success' })
  18. }).catch((err) => {
  19.   console.error('失败:', err)
  20.   uni.showToast({ title: '上传失败', icon: 'none' })
  21. })
复制代码

批量上传与临时链接获取
批量上传图片时,原文使用 type 为 image、sourceType 为 album、count 为 9、sizeType 为 compressed;进度回调中的 progress.index 可用于判断当前是第几张。上传结束后遍历 res.tempFiles 即可拿到每张图片的 url。获取临时链接时,单文件和批量都走 getTempFileURL,只需传入 fileList,返回后遍历 res.fileList,其中 item.fileID 对应原文件,item.tempFileURL 就是临时访问地址。
  1. uniCloud.getTempFileURL({
  2.   fileList: ['cloud://xxx/images/avatar.jpg']
  3. }).then((res) => {
  4.   res.fileList.forEach((item) => {
  5.     console.log('fileID:', item.fileID)
  6.     console.log('临时链接:', item.tempFileURL)
  7.   })
  8. }).catch((err) => {
  9.   console.error('获取链接失败:', err)
  10. })
复制代码

上传后保存 fileID 到数据库
文件上传成功只是第一步,业务数据通常还要记录文件归属。原文示例先上传文件,再用 uniCloud.databaseForJQL() 获取数据库实例,向 files 集合 add 一条记录,保存 fileID、cloudPath、originalName 和 uploadTime,并给 add 参数加上 as UTSJSONObject。这样后续可以根据业务记录中的 fileID 再调用 getTempFileURL 换取临时链接。
  1. const uploadAndSave = (filePath: string) => {
  2.   const timestamp = Date.now()
  3.   const ext = filePath.split('.').pop() || 'jpg'
  4.   const cloudPath = 'images/' + timestamp + '.' + ext
  5.   uni.showLoading({ title: '上传中...' })
  6.   uniCloud.uploadFile({
  7.     filePath: filePath,
  8.     cloudPath: cloudPath
  9.   }).then((res) => {
  10.     const db = uniCloud.databaseForJQL()
  11.     return db.collection('files').add({
  12.       fileID: res.fileID,
  13.       cloudPath: cloudPath,
  14.       originalName: filePath.split('/').pop(),
  15.       uploadTime: Date.now()
  16.     } as UTSJSONObject)
  17.   }).then((res) => {
  18.     uni.hideLoading()
  19.     console.log('上传并保存成功')
  20.     uni.showToast({ title: '上传成功', icon: 'success' })
  21.   }).catch((err) => {
  22.     uni.hideLoading()
  23.     console.error('上传或保存失败:', err)
  24.     uni.showToast({ title: '上传失败', icon: 'none' })
  25.   })
  26. }
复制代码

页面落地与排障思路
原文的完整页面使用 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 简单太多。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-9-30 10:44 , Processed in 0.023809 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部