#import "ViewController.h"
@interface ViewController ()<NSURLConnectionDataDelegate>
@property (nonatomic, assign) long long fileSize; // 文件总大小
@property (nonatomic, assign) long long currentSize; // 当前接收的文件大小
@property (nonatomic, strong) NSOutputStream *output; // 文件输出流
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// [self serverFileSize];
}
// 我们在使用别人的软件的时候,点击下载会怎么样?
// 提示这个文件是多大,是否下载
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self serverFileSize];
}
// HEAD用来请求查看文件大小
- (void)serverFileSize {
// NSURL
NSString *URLStr =@"http://localhost/01UI基础复习.mp4";
// 百分号转码
URLStr = [URLStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:URLStr];
// NSURLRequest 获取文件大小,不是使用GET,而是使用HEAD
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"HEAD"];
NSURLResponse *response;
// 获取文件大小,是使用同步
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:NULL];
// 文件总大小
// NSLog(@"%@",response);
self.fileSize = response.expectedContentLength;
// NSLog(@"%lld",fileSize);
// 提示用户文件总大下,是否需要下载
// 下载文件
[self download:url];
}
- (void)download:(NSURL *)url {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
// NSURLRequest 下载文件,从服务器获取的意思 GET
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 开始下载文件, 知道下载的进度
// 代理回调的线程,跟执行这一行代码的线程是同一个
[NSURLConnection connectionWithRequest:request delegate:self];
// NSLog(@"开始下载文件");
// 开启运行循环,才能让子线程保持
[[NSRunLoop currentRunLoop] run];
});
}
#pragma mark - NSURLConnection 代理
/**
NSFileHandle 选择写入文件的方式初始化,在写入文件之前先把光标移动文件的最后,写完之后关闭
NSOutputStream 初始化的时候选择拼接文件,再打开流,写入数据(多次),关闭流
*/
// 接收到响应
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(@"接收到响应%@ -- %lld",response,response.expectedContentLength);
// NSHTTPURLResponse *httpResp
// self.fileSize = response.expectedContentLength; // 文件总大小
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"123.mp4"];
self.output = [[NSOutputStream alloc]initToFileAtPath:path append:YES];
// 在写入编辑文件之前,打开文件
[self.output open];
}
// 如果代理方法在主线程中执行
/**
1. 方法会调用很多次
2. 如果主线程没空,不会调用代理(视力滚动的时候,或者在做其他事情),也就是相当于不下载
*/
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
// NSLog(@"接收到数据 %zd",data.length);
// 如果需要知道进度,首要要知道文件的总大小,还要接收了多少
self.currentSize += data.length;
NSLog(@"%f",(CGFloat)self.currentSize / self.fileSize);
// uunt8_t -> NSData
// [NSData dataWithBytes:<#(nullable const void *)#> length:<#(NSUInteger)#>]
[self.output write:data.bytes maxLength:data.length];
NSLog(@"%@",[NSThread currentThread]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(@"下载完成了");
// 关闭文件流
[self.output close];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(@"出错了");
}
@end
网络:使用多线程下载文件
最新推荐文章于 2022-05-27 16:52:28 发布