一,正确保存文件的位置
iOS 开发中,音频或者视频是非常耗费内存的东西,所以如果文件存放的地方不对的话将会不断的占用系统的内存容量,毕竟手机的内存是有限的,所以我们开发人员必须合理的管理内存资源。所以为了合理的管理音频和视频的文件资源,我们一般将这些占用内存比较大的资源存放到缓存中,如果清空缓存的时候,就会自动清理这些资源,从而释放内存。所以我们导入AFNetWorking 第三方库。
二,进行相关的下载工作
(1)首先获取沙河路径,从而更好的获取缓存路径
NSArray *firstPathArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);//获取沙河路径
NSString *firthPath = [firstPathArray firstObject];//获取缓存
(2)其次,在缓存路径中创建一个专门存放mp3文件的文件夹,
NSString *allFilePath = [firthPath stringByAppendingPathComponent:@"MP3File"];//创建一个MP3File文件夹,
BOOL isDir = NO;
BOOL isExisted = [fileManager fileExistsAtPath:mp3FielPath isDirectory:&isExisted];//坚持文件夹是否存在
if (!(isDir == YES && isExisted == YES)) {//确保文件夹一定会被创建成果,以便于音频文件的存储
[fileManager createDirectoryAtPath:mp3FielPath withIntermediateDirectories:YES attributes:nil error:nil];
}
注:如果没有这个if语句判断,文件夹很可能没有被执行创建,音频文件也没法存储,从而也就不能播放
(3)获取下载单词mp3文件的路径,(这里是根据词道单词ID 进行生成下载路径)
YOWordModel *wordModel = [[DataBaseManager shareDataBaseManager]getWordAndWordIDAccrodingToBookWordID:bookWordID];//从数据库中选取单词的意思和ID
NSString *nameFile = [[VoiceRoldClass shareVoiceLoad]makeBackLockedWayToSaveLoadAccrodingToWordID:wordModel.wordID];//选出单词发音的字段通过md5加密生成最终存放在文件夹里的文件名
NSString *downloadPath = [[VoiceRoldClass shareVoiceLoad]makeWordDownloadWayAccrodingToWordID:wordModel.wordID andWord:wordModel.word];//得到最终的下载路径
三,文件操作
文件操作顾名思义就是优先从文件中读取相应的文件内容,如果文件夹中有当前需要播放的语音文件,就直接从文件夹从取数据进行相应的操作,不用来回的请求服务器,节省资源,也减少了对服务器的响应,所以在此本人在数据库中插入了一张表来专门记录此单词是否已经被下载过,通过查询数据库就可以知道是否需要请求服务器。
BOOL isDownloaded = [[DataBaseManager shareDataBaseManager]getWordMP3isDownloadedfromWordDownloadTableAccrodingToBookWordID:wordModel.wordID];
如果该单词的文件被下载了,所以我们根据上边所生成的文件名之间去文件中读取MP3文件,直接采用AVAudioPlayer读取mp3文件,
if (isDownloaded == YES) {
[fileManager createDirectoryAtPath:allFilePath withIntermediateDirectories:YES attributes:nil error:nil];;//拷贝创建的文件夹
NSString *lastPath = [allFilePath stringByAppendingPathComponent:destinationFile];
BOOL isExistTheMp3File = [fileManager fileExistsAtPath:lastPath];//判断文件是否存在
if (isExistTheMp3File) {
_player = [[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL URLWithString:lastPath] error:nil];
_player.delegate = self;
[_player play];//播放语音
}
如果mp3文件没有存在本地,那就要直接去访问服务器,并且直接播放。甚至要进行写入文件夹操作,
四,去服务器下载文件
用AFNetWorking 下载文件,先要创建一个任务配置文件,这是下载文件必须必备的
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *sessionManager = [[AFURLSessionManager alloc]initWithSessionConfiguration:configuration];
注,在下载服务器中应该注意几种特殊的情况,在下载路径有特殊字符的时候要进行转义,否则改文件无法下载成功。例如:空格,@ , %等等,具体的转义字符自己了解。
转义操作如下,
if ([downloadPath containsString:@" "]) {
NSArray *newArray = [string componentsSeparatedByString:@" "];
NSString *newString = [newArray componentsJoinedByString:@"%20"];
lastString = newString;//空格的转义用@“20%”代替,其他的同理
}
执行下载文件的方法
NSURLRequest *requestSound = [NSURLRequest requestWithURL:[NSURL URLWithString:lastString]];//生成request文件
NSURLSessionDownloadTask *downloadTask = [sessionManager downloadTaskWithRequest:requestSound progress:nil destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {//此代码块中需要返回的是最终生成音频存储文件的二进制文件,所以和上边生成存储的是一样的文件,不同的是此代码块自动转二进制,不需要人为操纵。
NSURL *downloadURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
这里通过相应文件的.进行分割,旨在获取通过获取前半部分字符串来加密,从而确保文件夹中存放的音频文件和准备下载所生成的代码完全一致,从而更好的读取本地文件
NSString *tempString = [[[response suggestedFilename]componentsSeparatedByString:@"."]firstObject];
NSString *secString =[[[response suggestedFilename]componentsSeparatedByString:@"."]lastObject];
NSString *lastName = [[MyMD5 md5:tempString]stringByAppendingString:[NSString stringWithFormat:@".%@",secString]];
return [downloadURL URLByAppendingPathComponent:[NSString stringWithFormat:@"MP3File/%@",lastName]];
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
//下载完毕 将文件写入文件夹
NSData *data = [NSData dataWithContentsOfURL:filePath];
[data writeToURL:filePath atomically:YES];
_player = [[AVAudioPlayer alloc]initWithContentsOfURL:filePath error:nil];//直接播放
_player.delegate = self;
[_player play];
}];
[downloadTask resume];//完全下载文件流程,