端侧调用云存储实现头像存储
·
一、端侧调用云存储上传头像
云存储是一种可伸缩、免维护的云端存储服务,可用于存储图片、音频、视频或其他由用户生成的内容。借助云存储服务,您可以无需关心存储服务器的开发、部署、运维、扩容等事务,大大降低了应用使用存储的门槛,让您可以专注于应用的业务能力构建,助力您的商业成功。
云存储提供了客户端和服务端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 directory
const 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 listener
this.addEventListener(task, this.onUploadCompleted(cloudPath, cacheFilePath));
// start task
task.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();
// 过滤选择媒体文件类型为IMAGE
photoSelectOptions.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 finished
fileIo.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');
}
}
二、课程总结
通过十小节课程的学习,相信大家已经完全掌握了端云一体化开发流程,能够独立完成云函数开发、调试、部署、以及调用,独立完成云数据库设计、开发、部署、以及调用,以及云存储的端侧调用。
更多推荐
所有评论(0)