生活随笔
收集整理的這篇文章主要介紹了
iOS 开发-文件下载原理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
創建文件上傳類FileDownload.h //
// FileDownload.h
// 01.文件下載
//
// Created by wyh on 15-1-29.
// Copyright (c) 2015年 itcast. All rights reserved.
//
#import <Foundation/Foundation.h>@interface FileDownload : NSObject- (void)downloadFileWithURL:(NSURL *)url completion:(void (^)(UIImage *image))completion;@end ?
創建文件上傳類FileDownload.m //
// FileDownload.m
// 01.文件下載
//
// Created by wyh on 15-1-29.
// Copyright (c) 2015年 itcast. All rights reserved.
//
#import "FileDownload.h"
#import "NSString+Password.h"#define kTimeOut 2.0f
// 每次下載的字節數
#define kBytesPerTimes 20250@interface FileDownload()
@property (nonatomic, strong) NSString *cacheFile;
@property (nonatomic, strong) UIImage *cacheImage;
@end@implementation FileDownload
/**為了保證開發的簡單,所有方法都不使用多線程,所有的注意力都保持在文件下載上在開發中如果碰到比較繞的計算問題時,建議:1> 測試數據不要太大2> 測試數據的數值變化,能夠用筆算計算出準確的數值3> 編寫代碼對照測試*/
//- (NSString *)cacheFile
//{
// if (!_cacheFile) {
// NSString *cacheDir = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
// _cacheFile = [cacheDir stringByAppendingPathComponent:@"123.png"];
// }
// return _cacheFile;
//}
- (UIImage *)cacheImage
{if (!_cacheImage) {_cacheImage = [UIImage imageWithContentsOfFile:self.cacheFile];}return _cacheImage;
}- (void)setCacheFile:(NSString *)urlStr
{NSString *cacheDir = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];urlStr = [urlStr MD5];_cacheFile = [cacheDir stringByAppendingPathComponent:urlStr];
}- (void)downloadFileWithURL:(NSURL *)url completion:(void (^)(UIImage *image))completion
{// GCD中的串行隊列異步方法dispatch_queue_t q = dispatch_queue_create("cn.itcast.download", DISPATCH_QUEUE_SERIAL);dispatch_async(q, ^{NSLog(@"%@", [NSThread currentThread]);// 把對URL進行MD5加密之后的結果當成文件名self.cacheFile = [url absoluteString];// 1. 從網絡下載文件,需要知道這個文件的大小long long fileSize = [self fileSizeWithURL:url];// 計算本地緩存文件大小long long cacheFileSize = [self localFileSize];if (cacheFileSize == fileSize) {dispatch_async(dispatch_get_main_queue(), ^{completion(self.cacheImage);});NSLog(@"文件已經存在");return;}// 2. 確定每個數據包的大小long long fromB = 0;long long toB = 0;// 計算起始和結束的字節數while (fileSize > kBytesPerTimes) {// 20480 + 20480//
toB = fromB + kBytesPerTimes - 1;// 3. 分段下載文件
[self downloadDataWithURL:url fromB:fromB toB:toB];fileSize -= kBytesPerTimes;fromB += kBytesPerTimes;}[self downloadDataWithURL:url fromB:fromB toB:fromB + fileSize - 1];dispatch_async(dispatch_get_main_queue(), ^{completion(self.cacheImage);}); });
}#pragma mark 下載指定字節范圍的數據包
/**NSURLRequestUseProtocolCachePolicy = 0, // 默認的緩存策略,內存緩存NSURLRequestReloadIgnoringLocalCacheData = 1, // 忽略本地的內存緩存NSURLRequestReloadIgnoringCacheData*/
- (void)downloadDataWithURL:(NSURL *)url fromB:(long long)fromB toB:(long long)toB
{NSLog(@"數據包:%@", [NSThread currentThread]);NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:kTimeOut];// 指定請求中所要GET的字節范圍NSString *range = [NSString stringWithFormat:@"Bytes=%lld-%lld", fromB, toB];[request setValue:range forHTTPHeaderField:@"Range"];NSLog(@"%@", range);NSURLResponse *response = nil;NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:NULL];// 寫入文件,覆蓋文件不會追加
// [data writeToFile:@"/Users/aplle/Desktop/1.png" atomically:YES];
[self appendData:data];NSLog(@"%@", response);
}#pragma mark - 讀取本地緩存文件大小
- (long long)localFileSize
{// 讀取本地文件信息NSDictionary *dict = [[NSFileManager defaultManager] attributesOfItemAtPath:self.cacheFile error:NULL];NSLog(@"%lld", [dict[NSFileSize] longLongValue]);return [dict[NSFileSize] longLongValue];
}#pragma mark - 追加數據到文件
- (void)appendData:(NSData *)data
{// 判斷文件是否存在NSFileHandle *fp = [NSFileHandle fileHandleForWritingAtPath:self.cacheFile];// 如果文件不存在創建文件if (!fp) {[data writeToFile:self.cacheFile atomically:YES];} else {// 如果文件已經存在追加文件// 1> 移動到文件末尾
[fp seekToEndOfFile];// 2> 追加數據
[fp writeData:data];// 3> 寫入文件
[fp closeFile];}
}#pragma mark - 獲取網絡文件大小
- (long long)fileSizeWithURL:(NSURL *)url
{// 默認是GETNSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:kTimeOut];// HEAD 頭,只是返回文件資源的信息,不返回具體是數據// 如果要獲取資源的MIMEType,也必須用HEAD,否則,數據會被重復下載兩次request.HTTPMethod = @"HEAD";// 使用同步方法獲取文件大小NSURLResponse *response = nil;[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:NULL];// expectedContentLength文件在網絡上的大小NSLog(@"%lld", response.expectedContentLength);return response.expectedContentLength;
}@end ?
控制器中調用 //
// ViewController.m
// 01.文件下載
//
// Created by wyh on 15-1-29.
// Copyright (c) 2015年 itcast. All rights reserved.
//
#import "ViewController.h"
#warning 包含FileDownload.h文件
#import "FileDownload.h"@interface ViewController ()
@property (nonatomic, strong) FileDownload *download;
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end@implementation ViewController- (void)viewDidLoad
{[super viewDidLoad];
#warning 創建FileDownload對象,并調用方法downloadFileWithURL:self.download = [[FileDownload alloc] init];[self.download downloadFileWithURL:[NSURL URLWithString:@"http://localhost/itcast/images/head4.png"] completion:^(UIImage *image) {self.imageView.image = image;}];
}@end ?
轉載于:https://www.cnblogs.com/wangyinghui/p/4356711.html
總結
以上是生活随笔為你收集整理的iOS 开发-文件下载原理的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。