公司项目有集成百度合成语音 API 需求,而 API 在下载 mp3 文件的时候需要使用 x-www-form-urlencoded 格式请求文件下载,但谷歌找的代码都不符合需求,所以有了这篇文章。
由于 AFNetworking3.0 及以上封装的最外层 AFHTTPSessionManager 的 POST 方法不能完成 application/x-www-form-urlencoded 的请求, 所以必须自己作出一些定制。
首先,正常的 AFNetworking Post 方法已经不适用了,要自己初始化一个符合要求的 Request 。
// 初始化Request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:15.0];
// http method
[request setHTTPMethod:@"POST"];
// http header
// 这一步设置请求格式,是重点
[request addValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
然后设置 HTTPBody,
// http body
NSMutableString *paraString = [NSMutableString string];
for (NSString *key in [params allKeys]) {
[paraString appendFormat:@"&%@=%@", key, params[key]];
}
[paraString deleteCharactersInRange:NSMakeRange(0, 1)]; // 删除多余的&号
[request setHTTPBody:[paraString dataUsingEncoding:NSUTF8StringEncoding]];
最后构建一个 AFManager 并发送请求下载文件。
整个完整代码如下:
+ (void)downloadMp3FileWithText:(NSString *)text token:(NSString *)token progres:(void(^)(CGFloat percent))progress completion:(void (^)(NSURL * mp3FilePath))completion{
// 初始化URL
NSURL *URL = [NSURL URLWithString:@"https://tsn.baidu.com/text2audio"];
// 初始化参数
NSDictionary * params = @{
@"tex":text,
@"tok":token,
@"cuid":@"4234234",
@"ctp":@"1",
@"lan":@"zh",
};
// 初始化Request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:15.0];
// http method
[request setHTTPMethod:@"POST"];
// http header
// 这一步是重点
[request addValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
// http body
NSMutableString *paraString = [NSMutableString string];
for (NSString *key in [params allKeys]) {
[paraString appendFormat:@"&%@=%@", key, params[key]];
}
[paraString deleteCharactersInRange:NSMakeRange(0, 1)]; // 删除多余的&号
[request setHTTPBody:[paraString dataUsingEncoding:NSUTF8StringEncoding]];
// 初始化AFManager
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration: [NSURLSessionConfiguration defaultSessionConfiguration]];
AFJSONResponseSerializer *serializer = [AFJSONResponseSerializer serializer];
serializer.acceptableContentTypes = [NSSet setWithObjects:
@"text/plain",
@"application/json",
@"text/html", nil];
manager.responseSerializer = serializer;
//下载Task操作
NSURLSessionDownloadTask *_downloadTask = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
//进度
if(progress){
progress(downloadProgress.fractionCompleted);
}
} destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *path = [cachesPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%u%@",arc4random_uniform(100000),response.suggestedFilename]];
return [NSURL fileURLWithPath:path];
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
// filePath就是你下载文件的位置,你可以解压,也可以直接拿来使用
if (error) {
if(completion){
completion(nil);
}
} else {
if(completion){
completion(filePath);
}
}
}];
[_downloadTask resume];
}
上面的代码也涉及到了如何下载一个文件,希望能帮助到大家。