M3(批5): AudioProvider 播放 + 七牛上传器(@qiniu/upload)
依赖:ohpm i @qiniu/upload@1.0.2(platform)
platform QiniuUploader:UploadFile.fromPath + key + createMultipartUploadV2Task(context,file,{tokenProvider})。
🔴 token 走 tokenProvider(服务端用 AK/SK 生成 uploadToken(bucket)),AK/SK 不入端——纠正原 Android 硬编码 AK/SK
T-M3-10 AudioProvider(@kit.MediaKit AVPlayer):
- mediaTypeAudio:播放语音 url → gameui_play_voice/gameui_stop_voice(user 透传)
- srcIsloop:播放本地 wav(<gameDir>/assets/wav/<src>,isloop 0一次/>0循环/<0停止)
- voicePlaying:静音总开关 setVolume
- prepareaudio:录音分档(QiniuUploader 链路就绪;按住说话手势+麦克风+七牛服务端 token 三依赖未就绪前安全空实现)
bucket/域名/key 规则对齐原工程(bucket gameauio、回放 http://gameaudio.daoqi88.cn/<key>,由服务端 token 与 AudioProvider 接入时落地)
devecocli build 通过(CompileArkTS 编译七牛/音频无误)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -14,3 +14,4 @@ export { Unzipper } from './src/main/ets/zip/Unzipper';
|
||||
// 权限 / 上传服务
|
||||
export { PermissionGuard } from './src/main/ets/perm/PermissionGuard';
|
||||
export { LocalUploadServer } from './src/main/ets/upload/LocalUploadServer';
|
||||
export { QiniuUploader, QiniuTokenProvider } from './src/main/ets/upload/QiniuUploader';
|
||||
|
||||
@@ -6,10 +6,18 @@
|
||||
"lockfileVersion": 3,
|
||||
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
|
||||
"specifiers": {
|
||||
"@qiniu/upload@^1.0.2": "@qiniu/upload@1.0.2",
|
||||
"common@../common": "common@../common",
|
||||
"contracts@../contracts": "contracts@../contracts"
|
||||
},
|
||||
"packages": {
|
||||
"@qiniu/upload@1.0.2": {
|
||||
"name": "@qiniu/upload",
|
||||
"version": "1.0.2",
|
||||
"integrity": "sha512-LWUgUSXo7KSHZ9DaTTso7D7t5VUJqLNu3vPkEdhVNSnjbajqeK8X4yIuWKp9MqCHCyB9KjHSvliRrt4A0ukQ5A==",
|
||||
"resolved": "https://ohpm.openharmony.cn/ohpm/@qiniu/upload/-/upload-1.0.2.har",
|
||||
"registryType": "ohpm"
|
||||
},
|
||||
"common@../common": {
|
||||
"name": "common",
|
||||
"version": "1.0.0",
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"contracts": "file:../contracts",
|
||||
"common": "file:../common"
|
||||
}
|
||||
}
|
||||
"common": "file:../common",
|
||||
"@qiniu/upload": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"dynamicDependencies": {}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 七牛云对象存储上传(@qiniu/upload,契约 §10.6 录音上传)。
|
||||
*
|
||||
* 🔴 安全(CLAUDE.md 附录 B / §14.2):上传 token 由 **tokenProvider 异步提供**,
|
||||
* 应由服务端用 AK/SK 生成 uploadToken(bucket) 后下发;**AK/SK 绝不入客户端**。
|
||||
* 原 Android 把 AK/SK 硬编码在端侧,本平台用 tokenProvider 模式纠正。
|
||||
*/
|
||||
import { common } from '@kit.AbilityKit';
|
||||
import { createMultipartUploadV2Task, UploadFile, UploadConfig, UploadTask } from '@qiniu/upload';
|
||||
import { Logger } from 'common';
|
||||
|
||||
/** token 提供器:返回上传 token 的 Promise(来源应为服务端)。 */
|
||||
export type QiniuTokenProvider = () => Promise<string>;
|
||||
|
||||
export class QiniuUploader {
|
||||
private static readonly log: Logger = Logger.tag('QiniuUploader');
|
||||
|
||||
/**
|
||||
* 上传本地文件到七牛,资源名为 key。成功返回 true。
|
||||
* @param context UIAbility 上下文
|
||||
* @param localPath 本地文件路径
|
||||
* @param key 七牛资源名(= 回放 URL 的路径段)
|
||||
* @param tokenProvider 上传 token 提供器(服务端生成 uploadToken(bucket))
|
||||
*/
|
||||
static async upload(context: common.Context, localPath: string, key: string,
|
||||
tokenProvider: QiniuTokenProvider): Promise<boolean> {
|
||||
const file: UploadFile = UploadFile.fromPath(localPath);
|
||||
file.key = key;
|
||||
const config: UploadConfig = { tokenProvider };
|
||||
const task: UploadTask = createMultipartUploadV2Task(context, file, config);
|
||||
let failed: boolean = false;
|
||||
task.onError(() => {
|
||||
failed = true;
|
||||
});
|
||||
try {
|
||||
await task.start();
|
||||
} catch (e) {
|
||||
QiniuUploader.log.w(`upload start failed: ${(e as Error).message}`);
|
||||
return false;
|
||||
}
|
||||
if (failed) {
|
||||
QiniuUploader.log.w(`upload failed for key=${key}`);
|
||||
}
|
||||
return !failed;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user