当前位置: 首页 > news >正文

端侧调用云存储实现头像存储

一、端侧调用云存储上传头像

云存储是一种可伸缩、免维护的云端存储服务,可用于存储图片、音频、视频或其他由用户生成的内容。借助云存储服务,您可以无需关心存储服务器的开发、部署、运维、扩容等事务,大大降低了应用使用存储的门槛,让您可以专注于应用的业务能力构建,助力您的商业成功。

云存储提供了客户端和服务端SDK,您可以使用云存储SDK为您的应用实现安全可靠的文件上传和下载服务,同时具备如下优势。

  • 安全可靠:全流程使用HTTPS协议对用户的传输数据进行加密保护,并采用安全的加密协议将文件加密存储在云端。
  • 断点续传:因网络原因或用户原因导致的操作中止,只需要简单地传入操作中止的位置,就可以尝试重新开始该操作。
  • 可伸缩:提供EB级的数据存储,解决海量数据存储的难题。
  • 易维护:通过简单的判断返回异常就可以定位出错误原因,定位快捷方便。

云存储模块提供使用云存储对文件进行上传、下载、查询和删除等操作能力。以上传宝宝头像为例,端侧调用云存储需要以下操作步骤:

1)引入云存储模块

import {cloudStorage} from '@kit.CloudFoundataionKit';
import { BusinessError, request } from '@kit.BasicServicesKit';

2)初始化云存储实例

const bucket: cloudStorage.StorageBucket = cloudStorage.bucket();

3)调用云存储上传接口,上传图片

bucket.uploadFile(getContext(this), {localPath: cacheFilePath,cloudPath: cloudPath
})

4)调用云存储获取图片地址接口

bucket.getDownloadURL(cloudPath).then((downloadURL: string) => {this.imageUrl = downloadURL;
})

完整代码:

import { cloudFunction, cloudDatabase, cloudStorage } from '@kit.CloudFoundationKit';
import { BusinessError, request } from '@kit.BasicServicesKit';
import { SymbolGlyphModifier } from '@kit.ArkUI';import { Feeding } from '../model/Feeding';
import { fileIo } from '@kit.CoreFileKit';
import { photoAccessHelper } from '@kit.MediaLibraryKit';const bucket: cloudStorage.StorageBucket = cloudStorage.bucket();
type UploadCompleteCallback = (uploadSuccess: boolean) => void;interface BabyAge {years: number;months: number;days: number;totalDays: number;
}interface ResponseBody {code: number;desc: string;data: BabyAge
}@Entry
@Component
struct Index {controller: SearchController = new SearchController();@State birthday: string = "";@State callFunctionResult: BabyAge | undefined = undefined;currentDateTime: Date = new Date();condition: cloudDatabase.DatabaseQuery<Feeding> = new cloudDatabase.DatabaseQuery(Feeding);private databaseZone = cloudDatabase.zone("default");@State allFeedingList: Feeding[] = [];@State feeding: Feeding = new Feeding();@State isFeeding: boolean = false;@State startTime: Date = new Date();@State imageUrl: string | ResourceStr = $r('app.media.empty_image');// 查询当前喂养记录信息async queryAllFeeding() {try {// 构建查询条件const queryCondition = this.condition.greaterThanOrEqualTo("startTime", this.currentDateTime.setHours(0, 0, 0, 0)).and().lessThanOrEqualTo("startTime", this.currentDateTime.setHours(23, 59, 59, 999));const result = await this.databaseZone.query(queryCondition);if (result.length > 0) {this.allFeedingList = result;}} catch (error) {// 异常处理this.allFeedingList = [];}}// 新增喂养记录async insertFeeding(feeding: Feeding) {await this.databaseZone.upsert(feeding);await this.queryAllFeeding();}// 删除数据async deleteFeeding(feeding: Feeding) {try {await this.databaseZone.delete(feeding);await this.queryAllFeeding();} catch (error) {const err: BusinessError = error;this.getUIContext().getPromptAction().showToast({message: err.message})}}async aboutToAppear(): Promise<void> {this.queryAllFeeding();}build() {Column({ space: 10 }) {Text("请先设置宝宝出生日期").fontColor(Color.Grey).height(54)Search({ controller: this.controller, value: this.birthday }).width('90%').height('54vp').searchIcon(new SymbolGlyphModifier($r('sys.symbol.calendar_badge_play')).fontColor([Color.Grey]).fontSize('30fp')).cancelButton({style: CancelButtonStyle.INVISIBLE}).borderRadius('8vp').onClick(() => {CalendarPickerDialog.show({selected: new Date(this.birthday),acceptButtonStyle: {style: ButtonStyleMode.EMPHASIZED},cancelButtonStyle: {fontColor: Color.Grey},onAccept: async (value) => {this.birthday = value.toLocaleDateString();console.info("calendar onAccept:" + JSON.stringify(value))let result: cloudFunction.FunctionResult = await cloudFunction.call({name: 'calculate-baby-age',version: '$latest',timeout: 10 * 1000,data: {birthday: this.birthday}});let body = result.result as ResponseBody;this.callFunctionResult = body.data;}})})if (this.callFunctionResult !== undefined) {Row() {Column({ space: 8 }) {Image(this.imageUrl).width(64).height(64).borderRadius(16).onClick(() => {this.upLoadImage();})Text(`我已经${this.callFunctionResult.years}岁了 ${this.callFunctionResult.months}${this.callFunctionResult.days}天了~`)Text(`我已经出生${this.callFunctionResult.totalDays}天了~`)}.width('100%')}.width('90%')Button(`${this.isFeeding ? '停止喂养' : '开始喂养'}`).backgroundColor(this.isFeeding ? Color.Orange : Color.Green).onClick(async () => {this.isFeeding = !this.isFeeding;if (this.isFeeding) {this.startTime = new Date();this.feeding.id = this.allFeedingList.length + 1;this.feeding.startTime = this.startTime;} else {this.feeding.totalDuration = new Date().getTime() - this.startTime.getTime();await this.insertFeeding(this.feeding);}})if (this.allFeedingList.length > 0) {List() {ForEach(this.allFeedingList, (item: Feeding) => {ListItem() {Column({ space: 8 }) {Row() {Text(`${item.type}喂养`)Text(`${item.startTime.toLocaleDateString()}`)}.width('100%').height(32).justifyContent(FlexAlign.SpaceBetween)Text(`总喂养时长:${item.totalDuration >= (60 * 1000) ? (item.totalDuration / (60 * 1000)) + 'm' : (item.totalDuration / 1000) + 's'}`).width('100%').height(32)Row() {Button("删除").onClick(async () => {this.getUIContext().getPromptAction().showDialog({title: '温馨提示',message: '确定要删除该喂养记录吗?',buttons: [{text: '取消',color: '#D3D3D3'},{text: '确定',color: '#FF5277'}],}).then(async data => {console.info('showDialog success, click button: ' + data.index);if (data.index === 1) {await this.deleteFeeding(item);}}).catch((err: Error) => {console.info('showDialog error: ' + err);})})}.width('100%')}.backgroundColor(0xf2f2f2).padding(12).borderRadius(8)}})}.width('90%').height(450).divider({strokeWidth: 2,color: Color.White})}}}.width('100%').height('100%')}private upLoadImage() {this.selectImage().then((selectImageUri: string) => {if (!selectImageUri) {return;}this.initStates();// copy select file to cache directoryconst fileName = selectImageUri.split('/').pop() as string;const cacheFilePath = `${getContext().cacheDir}/${fileName}`;this.copyFile(selectImageUri, cacheFilePath);const cloudPath = `default-bucket-lg41j/image_${new Date().getTime()}.jpg`;bucket.uploadFile(getContext(this), {localPath: cacheFilePath,cloudPath: cloudPath}).then(task => {// add task event listenerthis.addEventListener(task, this.onUploadCompleted(cloudPath, cacheFilePath));// start tasktask.start().catch((err: BusinessError) => {});}).catch((err: BusinessError) => {});}).catch((err: Error) => {});}private async selectImage(): Promise<string> {return new Promise((resolve: (selectUri: string) => void, reject: (err: Error) => void) => {const photoSelectOptions = new photoAccessHelper.PhotoSelectOptions();// 过滤选择媒体文件类型为IMAGEphotoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;photoSelectOptions.maxSelectNumber = 1;new photoAccessHelper.PhotoViewPicker().select(photoSelectOptions).then((photoSelectResult: photoAccessHelper.PhotoSelectResult) => {resolve(photoSelectResult.photoUris[0]);}).catch((err: Error) => {reject(err);});});}private addEventListener(task: request.agent.Task, completeCallback: UploadCompleteCallback) {task.on('progress', (progress) => {});task.on('completed', (progress) => {completeCallback(true);});task.on('response', (response) => {});task.on('failed', (progress) => {completeCallback(false);});}private onUploadCompleted(cloudPath: string, cacheFilePath: string) {return (uploadSuccess: boolean) => {if (uploadSuccess) {bucket.getDownloadURL(cloudPath).then((downloadURL: string) => {this.imageUrl = downloadURL;}).catch((err: BusinessError) => {});}// delete cache file when task finishedfileIo.unlink(cacheFilePath).catch((err: BusinessError) => {});};}private copyFile(src: string, dest: string) {const srcFile = fileIo.openSync(src);const dstFile = fileIo.openSync(dest, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);fileIo.copyFileSync(srcFile.fd, dstFile.fd);fileIo.closeSync(srcFile);fileIo.closeSync(dstFile);}private initStates() {this.imageUrl = $r('app.media.empty_image');}
}

二、课程总结

通过十小节课程的学习,相信大家已经完全掌握了端云一体化开发流程,能够独立完成云函数开发、调试、部署、以及调用,独立完成云数据库设计、开发、部署、以及调用,以及云存储的端侧调用。

相关文章:

  • 查看shell选项状态命令详解
  • CentOS7.6 yum无法下载
  • 《HTTP权威指南》 第14章 安全HTTP
  • 小木的算法日记——合成两个有序链表
  • 系统思考:救火先放火
  • 优化通义大模型推理性能:企业级场景下的延迟与成本削减策略
  • 桌面小屏幕实战课程:DesktopScreen 3 Git工具使用
  • 21.安卓逆向2-frida hook技术-HookOkHttp的拦截器
  • 数智管理学(二十四)
  • C++ -- AVL树的插入和旋转
  • Linux 线程调度管理函数
  • leetcode:21. 合并两个有序链表
  • 华为云Flexus+DeepSeek征文|基于Dify构建解析网页写入Notion笔记工作流
  • 【C++】C++枚举、const、static的用法
  • LLM存储优化:大量长对话解决方案
  • C++ - 标准库之 <string> npos(npos 概述、npos 的作用)
  • 开发云数据库
  • 数据库索引结构 B 树、B + 树与哈希索引在不同数据查询场景下的适用性分析
  • 深入剖析Flink内存管理:架构、调优与实战指南
  • 透视618:头部主播隐退、购物氛围变淡,新秩序正在建立
  • 做网站要什么专业/神马seo服务
  • 国外psd网页模板网站/网站推广如何引流
  • 自己怎么做卡密网站/曼联vs曼联直播
  • 怎样设计个人网站/推广联盟
  • 公司网站建设费用入账/seoul是什么品牌
  • 石狮新站seo/品牌策略