解决了语音上传到问题,接下来要解决下载播放问题

This commit is contained in:
joywayer
2025-06-15 12:36:47 +08:00
parent bba3ed1cb4
commit c11fc62bf1
513 changed files with 31197 additions and 2969 deletions

View File

@@ -43,6 +43,8 @@
#import <CommonCrypto/CommonDigest.h>
#import <AdSupport/ASIdentifierManager.h>
#import "XianliaoApiManager.h"
#import "QiniuManager.h"
#import "QiniuConfig.h"
@interface gameController ()
<WKNavigationDelegate,WXApiManagerDelegate,VoiceRecorderBaseVCDelegate,AVAudioPlayerDelegate,ASIHTTPRequestDelegate,AMapLocationManagerDelegate,UIActionSheetDelegate,AgoraRtcEngineDelegate>
{
@@ -844,7 +846,7 @@
CTTelephonyNetworkInfo *telephonyInfo = [[CTTelephonyNetworkInfo alloc] init];
CTCarrier *carrier = [telephonyInfo subscriberCellularProvider];
NSString *currentCountry=[carrier carrierName];
// NSLog(@"[carrier isoCountryCode]==%@,[carrier allowsVOIP]=%d,[carrier mobileCountryCode=%@,[carrier mobileCountryCode]=%@",[carrier isoCountryCode],[carrier allowsVOIP],[carrier mobileCountryCode],[carrier mobileNetworkCode]);
// NSLog(@"[carrier isoCountryCode]==%@,[carrier allowsVOIP]=%d,[carrier mobileCountryCode=%@,[carrier mobileNetworkCode]=%@",[carrier isoCountryCode],[carrier allowsVOIP],[carrier mobileCountryCode],[carrier mobileNetworkCode]);
UIDevice *device = [[UIDevice alloc] init];
// NSString *name = device.name; //
NSString *model = device.model; //
@@ -2194,6 +2196,15 @@
NSLog(@"录音时长过短,可能无效: %.2f秒", interval);
return;
}
//4.
if (play == nil)
{
NSLog(@"ERror creating player: %@", [play description]);
}else{
[play play];
}
NSString *amrPath = [FuncPublic GetPathByFileName:_fileName ofType:@"amr"];
NSLog(@"尝试转换WAV到AMR源文件: %@,目标文件: %@", _filePath, amrPath);
@@ -2223,23 +2234,67 @@
NSLog(@"转换WAV到AMR成功");
NSData *amrData = [NSData dataWithContentsOfFile:amrPath];
if (amrData && amrData.length > 0) {
//
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//text/html
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",
@"text/html",
@"image/jpeg",
@"image/png",
@"application/octet-stream",
@"text/json",
@"audio/amr",
nil];
NSString *string=@"http://gameapi.0791ts.cn/api/UpLoad/PostFile";
// 使QiniuManager
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat =@"yyyyMMddHHmmss";
NSString *str = [formatter stringFromDate:[NSDate date]];
NSString *fileName = [NSString stringWithFormat:@"%@%08X.amr", str, arc4random()];
// ...
formatter.dateFormat = @"yyyyMMddHHmmss";
NSString *timeStr = [formatter stringFromDate:[NSDate date]];
NSString *uniqueFileName = [NSString stringWithFormat:@"%@_%08X.amr", timeStr, arc4random()];
//
// UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示"
// message:@"正在上传录音文件..."
// preferredStyle:UIAlertControllerStyleAlert];
// [self presentViewController:alertController animated:YES completion:nil];
//
[[QiniuManager sharedManager] uploadAudioFile:amrPath
fileName:uniqueFileName
progressHandler:^(float progress) {
//
// dispatch_async(dispatch_get_main_queue(), ^{
// alertController.message = [NSString stringWithFormat:@"正在上传录音文件... %.0f%%", progress * 100];
// });
}
completionHandler:^(NSString *key, NSError *error) {
//
dispatch_async(dispatch_get_main_queue(), ^{
// [alertController dismissViewControllerAnimated:YES completion:nil];
if (error) {
//
// UIAlertController *errorAlert = [UIAlertController alertControllerWithTitle:@"上传失败"
// message:error.localizedDescription
// preferredStyle:UIAlertControllerStyleAlert];
// UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
// [errorAlert addAction:okAction];
// [self presentViewController:errorAlert animated:YES completion:nil];
//
NSLog(@"七牛云上传失败: %@", error);
} else {
// URL
NSString *fileUrl = [[QiniuManager sharedManager] getFileUrlWithKey:key];
NSString *audiourl=[NSString stringWithFormat:@"%@/%@",kQiniuDomain,uniqueFileName];
[_bridge callHandler:@"getaudiourl" data:@{ @"audiourl":audiourl,@"time":[NSString stringWithFormat:@"%ld",(long)time]} ];
NSLog(@"七牛云上传成功文件URL: %@", fileUrl);
// URLJS
if (self->_bridge) {
[self->_bridge callHandler:@"recordSuccess" data:@{
@"fileUrl": fileUrl,
@"fileName": uniqueFileName,
@"fileKey": key
}];
}
}
});
}];
//
} else {
NSLog(@"AMR文件无效或为空");
}
@@ -2476,3 +2531,5 @@
}}
@end

View File

@@ -0,0 +1,25 @@
//
// QiniuConfig.h
// msext
//
// Created on June 15, 2025.
//
#ifndef QiniuConfig_h
#define QiniuConfig_h
/* 七牛云相关配置常量 */
// AccessKey 和 SecretKey从七牛云控制台获取
extern NSString *const kQiniuAccessKey;
extern NSString *const kQiniuSecretKey;
// 存储空间名称
extern NSString *const kQiniuBucketName;
// 七牛云默认域名
extern NSString *const kQiniuDomain;
// 录音文件目录
extern NSString *const kQiniuRecordingDirectory;
#endif /* QiniuConfig_h */

View File

@@ -0,0 +1,22 @@
//
// QiniuConfig.m
// msext
//
// Created on June 15, 2025.
//
#import <Foundation/Foundation.h>
#import "QiniuConfig.h"
// AccessKey SecretKey
NSString *const kQiniuAccessKey = @"dQbQLUm1jIuL9PEq4jd6VKB-6pPxPEdg7le9KeBm";
NSString *const kQiniuSecretKey = @"RCZpwLhAPoQ2sQQyWXzMJc7Po2MyZWfUJeW4Jmfq";
//
NSString *const kQiniuBucketName = @"iosaudio";
// 访
NSString *const kQiniuDomain = @"iosaudio.daoqi88.cn";
//
NSString *const kQiniuRecordingDirectory = @"";

View File

@@ -0,0 +1,76 @@
//
// QiniuManager.h
// msext
//
// Created on June 15, 2025.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/**
* 上传完成后的回调
* @param key 文件在七牛云中的key
* @param error 错误信息如果上传成功则为nil
*/
typedef void(^QiniuUploadCompletionHandler)(NSString * _Nullable key, NSError * _Nullable error);
/**
* 下载完成后的回调
* @param filePath 下载文件的本地路径
* @param error 错误信息如果下载成功则为nil
*/
typedef void(^QiniuDownloadCompletionHandler)(NSString * _Nullable filePath, NSError * _Nullable error);
/**
* 进度回调
* @param progress 进度值范围0-1
*/
typedef void(^QiniuProgressHandler)(float progress);
@interface QiniuManager : NSObject
/**
* 获取QiniuManager的单例
* @return QiniuManager实例
*/
+ (instancetype)sharedManager;
/**
* 初始化七牛云SDK
*/
- (void)setupQiniuSDK;
/**
* 上传本地音频文件到七牛云
* @param filePath 本地文件路径
* @param fileName 上传后的文件名(不含路径)
* @param progressHandler 上传进度回调
* @param completionHandler 上传完成回调
*/
- (void)uploadAudioFile:(NSString *)filePath
fileName:(NSString *)fileName
progressHandler:(nullable QiniuProgressHandler)progressHandler
completionHandler:(QiniuUploadCompletionHandler)completionHandler;
/**
* 从七牛云下载音频文件
* @param key 文件在七牛云中的key
* @param progressHandler 下载进度回调
* @param completionHandler 下载完成回调
*/
- (void)downloadAudioFile:(NSString *)key
progressHandler:(nullable QiniuProgressHandler)progressHandler
completionHandler:(QiniuDownloadCompletionHandler)completionHandler;
/**
* 根据key获取七牛云文件的URL
* @param key 文件在七牛云中的key
* @return 完整的URL字符串
*/
- (NSString *)getFileUrlWithKey:(NSString *)key;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,256 @@
//
// QiniuManager.m
// msext
//
// Created on June 15, 2025.
//
#import "QiniuManager.h"
#import <QiniuSDK.h>
#import "QiniuConfig.h"
#import <objc/runtime.h>
#import <CommonCrypto/CommonHMAC.h>
#import <CommonCrypto/CommonDigest.h>
@implementation QiniuManager
+ (instancetype)sharedManager {
static QiniuManager *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
[instance setupQiniuSDK];
});
return instance;
}
- (void)setupQiniuSDK {
// Qiniu SDK doesn't require explicit initialization
// The configuration will be applied when creating the QNUploadManager instance
}
- (void)uploadAudioFile:(NSString *)filePath
fileName:(NSString *)fileName
progressHandler:(QiniuProgressHandler)progressHandler
completionHandler:(QiniuUploadCompletionHandler)completionHandler {
//
if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
NSError *error = [NSError errorWithDomain:@"QiniuManager" code:-1 userInfo:@{NSLocalizedDescriptionKey: @"上传文件不存在"}];
if (completionHandler) {
completionHandler(nil, error);
}
return;
}
//
QNConfiguration *config = [QNConfiguration build:^(QNConfigurationBuilder *builder) {
builder.zone = [QNFixedZone zone2]; // 使
builder.timeoutInterval = 60; //
}];
//
QNUploadManager *uploadManager = [[QNUploadManager alloc] initWithConfiguration:config];
NSString *token = [self generateUploadToken];
//
NSString *key = [NSString stringWithFormat:@"%@%@", kQiniuRecordingDirectory, fileName];
//
QNUploadOption *option = [[QNUploadOption alloc] initWithMime:@"audio/amr"
progressHandler:^(NSString *key, float percent) {
if (progressHandler) {
progressHandler(percent);
}
} params:nil checkCrc:NO cancellationSignal:nil];
//
[uploadManager putFile:filePath
key:key
token:token
complete:^(QNResponseInfo *info, NSString *key, NSDictionary *resp) {
if (info.statusCode == 200) {
if (completionHandler) {
completionHandler(key, nil);
}
} else {
NSError *error = [NSError errorWithDomain:@"QiniuManager"
code:info.statusCode
userInfo:@{NSLocalizedDescriptionKey: info.error.localizedDescription ?: @"上传失败"}];
if (completionHandler) {
completionHandler(nil, error);
}
}
}
option:option];
}
- (void)downloadAudioFile:(NSString *)key
progressHandler:(QiniuProgressHandler)progressHandler
completionHandler:(QiniuDownloadCompletionHandler)completionHandler {
// URL
NSString *urlString = [self getFileUrlWithKey:key];
NSURL *url = [NSURL URLWithString:urlString];
//
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
if (error) {
if (completionHandler) {
completionHandler(nil, error);
}
return;
}
// URL
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (httpResponse.statusCode != 200) {
NSError *downloadError = [NSError errorWithDomain:@"QiniuManager"
code:httpResponse.statusCode
userInfo:@{NSLocalizedDescriptionKey: @"下载失败"}];
if (completionHandler) {
completionHandler(nil, downloadError);
}
return;
}
// URL
NSString *fileName = [key lastPathComponent];
if ([fileName length] == 0) {
fileName = [NSString stringWithFormat:@"qiniu_download_%@", [[NSUUID UUID] UUIDString]];
}
//
NSString *cachesDirectory = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
NSString *downloadDirectory = [cachesDirectory stringByAppendingPathComponent:@"QiniuDownloads"];
//
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:downloadDirectory]) {
[fileManager createDirectoryAtPath:downloadDirectory withIntermediateDirectories:YES attributes:nil error:nil];
}
//
NSString *destinationPath = [downloadDirectory stringByAppendingPathComponent:fileName];
//
if ([fileManager fileExistsAtPath:destinationPath]) {
[fileManager removeItemAtPath:destinationPath error:nil];
}
NSError *moveError = nil;
[fileManager moveItemAtURL:location toURL:[NSURL fileURLWithPath:destinationPath] error:&moveError];
if (moveError) {
if (completionHandler) {
completionHandler(nil, moveError);
}
} else {
if (completionHandler) {
completionHandler(destinationPath, nil);
}
}
}];
//
if (progressHandler) {
[downloadTask addObserver:self forKeyPath:@"countOfBytesReceived" options:NSKeyValueObservingOptionNew context:NULL];
objc_setAssociatedObject(downloadTask, "progressHandler", [progressHandler copy], OBJC_ASSOCIATION_COPY);
objc_setAssociatedObject(downloadTask, "totalBytes", @(0), OBJC_ASSOCIATION_RETAIN);
}
//
[downloadTask resume];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([object isKindOfClass:[NSURLSessionDownloadTask class]]) {
NSURLSessionDownloadTask *task = (NSURLSessionDownloadTask *)object;
if ([keyPath isEqualToString:@"countOfBytesReceived"]) {
NSNumber *totalBytes = objc_getAssociatedObject(task, "totalBytes");
if ([totalBytes longLongValue] == 0 && task.countOfBytesExpectedToReceive > 0) {
objc_setAssociatedObject(task, "totalBytes", @(task.countOfBytesExpectedToReceive), OBJC_ASSOCIATION_RETAIN);
}
float progress = 0;
if (task.countOfBytesExpectedToReceive > 0) {
progress = (float)task.countOfBytesReceived / (float)task.countOfBytesExpectedToReceive;
}
QiniuProgressHandler progressHandler = objc_getAssociatedObject(task, "progressHandler");
if (progressHandler) {
dispatch_async(dispatch_get_main_queue(), ^{
progressHandler(progress);
});
}
}
}
}
- (NSString *)getFileUrlWithKey:(NSString *)key {
return [NSString stringWithFormat:@"%@/%@", kQiniuDomain, key];
}
#pragma mark - Private Methods
- (NSString *)generateUploadToken {
// (putPolicy)
NSMutableDictionary *policy = [NSMutableDictionary dictionary];
// bucketNamebucketName:keyPrefix
NSString *scope = [NSString stringWithFormat:@"%@", kQiniuBucketName];
[policy setObject:scope forKey:@"scope"];
// 1
NSInteger deadline = (NSInteger)[[NSDate dateWithTimeIntervalSinceNow:3600] timeIntervalSince1970];
[policy setObject:@(deadline) forKey:@"deadline"];
// JSON
NSError *error = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:policy options:0 error:&error];
if (error) {
NSLog(@"生成JSON数据失败: %@", error);
return nil;
}
// Base64JSON
NSString *encodedPolicy = [self urlsafeBase64EncodeData:jsonData];
// 使HMAC-SHA1encodedPolicy
NSData *signData = [encodedPolicy dataUsingEncoding:NSUTF8StringEncoding];
NSString *encodedSign = [self hmacSha1:kQiniuSecretKey data:signData];
// - : accessKey:encodedSign:encodedPolicy
NSString *uploadToken = [NSString stringWithFormat:@"%@:%@:%@", kQiniuAccessKey, encodedSign, encodedPolicy];
// NSLog(@"七牛云配置信息 - AccessKey: %@, BucketName: %@, Domain: %@",
// kQiniuAccessKey, kQiniuBucketName, kQiniuDomain);
// NSLog(@"生成的上传凭证: %@", uploadToken);
return uploadToken;
}
#pragma mark - Utility Methods
- (NSString *)urlsafeBase64EncodeData:(NSData *)data {
NSString *base64 = [data base64EncodedStringWithOptions:0];
base64 = [base64 stringByReplacingOccurrencesOfString:@"+" withString:@"-"];
base64 = [base64 stringByReplacingOccurrencesOfString:@"/" withString:@"_"];
return base64;
}
- (NSString *)hmacSha1:(NSString *)key data:(NSData *)data {
const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
const char *cData = [data bytes];
unsigned char cHMAC[CC_SHA1_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), cData, [data length], cHMAC);
NSData *hmacData = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
return [self urlsafeBase64EncodeData:hmacData];
}
@end