IOS斷點下載

來源:互聯網
上載者:User

標籤:

下載的一些用法

①對於小檔案,可以直接下載,無需斷點下載等處理。

 1 -(void)clickDownBtn{ 2     NSURL *url = [NSURL URLWithString:@"https://picjumbo.imgix.net/HNCK8461.jpg?q=40&w=1650&sharp=30"]; 3     if (self.imgView.image == nil) { 4         [self downLoad:url]; 5     }  6 } 7  8 //下載過程 9 -(void)downLoad:(NSURL *)url{10     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{11         NSData *imgData = [NSData dataWithContentsOfURL:url];12         UIImage *img = [UIImage imageWithData:imgData];13         if (imgData != nil) {14             dispatch_sync(dispatch_get_main_queue(), ^{15                 self.imgView.image = img;16             });17         }18     });19 }

需要注意的是,多線程中,資料處理是在子線程,UI更新是在主線程。若處理資料時沒有在子線程中進行,那麼會發生線程阻塞、介面卡死的情況。如下載圖片時,

-(void)downLoad:(NSURL *)url{    //資料處理(NSData)是在主線程中進行,所以會卡死    //況且這種寫法是沒有意義的,本來就在主線程,就無需再跳往主線程更新UI    NSData *imgData = [NSData dataWithContentsOfURL:url];    UIImage *img = [UIImage imageWithData:imgData];    if (imgData != nil) {        dispatch_sync(dispatch_get_main_queue(), ^{            self.imgView.image = img;        });    }}

正確的方法是,先開闢子線程,然後在主線程更新UI。

開闢子線程

-(void)downLoad:(NSURL *)url{    //開闢子線程    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        //操作    });}

async是非同步,sync是同步

 

②而對於大檔案,則可以使用NSURLSession實現暫停、斷點下載等操作。如下:
監聽下載進度,需要實現代理NSURLSessionDownloadDelegate,在這代理中常用的有3個方法

/** 下載完畢會調用,location為檔案臨時地址 */-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{    }
/** *  每次寫入沙箱完畢後調用,在這裡可以設定進度條資料等操作 *  totalBytesWritten/totalBytesExpectedToWrite,這兩個用來監視下載進度 * *  @param bytesWritten              這次寫入的大小 *  @param totalBytesWritten         已經寫入沙箱的大小 *  @param totalBytesExpectedToWrite 檔案總大小 */-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask               didWriteData:(int64_t)bytesWrittentotalBytesWritten:(int64_t)totalBytesWrittentotalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{    }
/** 恢複下載時使用 */-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes{    }

範例程式碼如下,在.m中

/** 展示進度的label */@property(nonatomic,strong) UILabel *progressLabel;/** 進度動畫 */@property(nonatomic,strong) UIProgressView *progressView;/** 下載按鈕 */@property(nonatomic,strong) UIButton *downBtn;/** 下載任務 */@property(nonatomic,strong) NSURLSessionDownloadTask *downLoadTask;/** 快取資料 */@property(nonatomic,strong) NSData *tempData;/** session */@property(nonatomic,strong) NSURLSession *session;

session的懶載入為

-(NSURLSession *)session{    if (!_session) {        NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration defaultSessionConfiguration];        _session = [NSURLSession sessionWithConfiguration:cfg delegate:self delegateQueue:[NSOperationQueue mainQueue]];    }    return _session;}

按鈕點擊事件如下:

//點擊下載按鈕-(void)clickDownBtn{    self.downBtn.selected = !self.downBtn.selected;    if (nil == self.downLoadTask) {        if (self.tempData) {            [self goOnDownload]; //繼續下載        } else { //從0開始下載            [self startDownload];        }    } else {        [self pauseDownload];    }}/** 開始下載 */-(void)startDownload{    NSURL *url = [NSURL URLWithString:@"http://11.gxdx2.crsky.com/201501/apkok-v3.0.zip"];        //建立任務    self.downLoadTask = [self.session downloadTaskWithURL:url];    //開始任務    [self.downLoadTask resume];}/** 暫停下載 */-(void)pauseDownload{    //防止循環參考    __weak typeof(self) weakSelf = self;    [self.downLoadTask cancelByProducingResumeData:^(NSData *resumeData) {        //resumeData包含了繼續下載的開始位置和url        weakSelf.tempData = resumeData;        weakSelf.downLoadTask = nil;    }];}/** 恢複下載 */-(void)goOnDownload{    //傳入上次暫停下載返回的資料,即可恢複下載    self.downLoadTask = [self.session downloadTaskWithResumeData:self.tempData];    [self.downLoadTask resume];    self.tempData = nil;}

實現2個代理方法,第3個暫時用不到

/** 下載完畢會調用,location為檔案臨時地址 */-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{    //選擇下載檔案路徑,檔案只能下載到該程式的目錄中    //下邊為下載到Documents檔案夾,若將NSDocumentDirectory換為NSCachesDirectory,則會下載到Cache檔案夾    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];    //response.suggestedFilename建議使用的檔案名稱,一般跟伺服器端的名稱一致    NSString *file = [caches stringByAppendingPathComponent:downloadTask.response.suggestedFilename];    //將臨時檔案複製或剪下到caches檔案夾    NSFileManager *fileManager = [NSFileManager defaultManager];    //AtPath : 剪下前的檔案路徑    //toPath : 剪下後的檔案路徑    //因為檔案都是下載到臨時檔案夾,下載完成後會刪除,所以必須移位置    [fileManager moveItemAtPath:location.path toPath:file error:nil];       // 提示下載完成    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"下載完成" message:downloadTask.response.suggestedFilename delegate:self cancelButtonTitle:nil otherButtonTitles: nil];    [alert show];    [self performSelector:@selector(dismissAlert:) withObject:alert afterDelay:2];        //將下載按鈕置灰    self.downBtn.selected = NO;    self.downBtn.enabled = NO;}/** *  每次寫入沙箱完畢後調用,在這裡可以設定進度條資料等操作 *  totalBytesWritten/totalBytesExpectedToWrite,這兩個用來監視下載進度 * *  @param bytesWritten              這次寫入的大小 *  @param totalBytesWritten         已經寫入沙箱的大小 *  @param totalBytesExpectedToWrite 檔案總大小 */-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask               didWriteData:(int64_t)bytesWrittentotalBytesWritten:(int64_t)totalBytesWrittentotalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{    //注意該處的progress,等號右邊必須強制轉換為double型,進度條才有動畫效果,否則只有在下載完成後才有    self.progressView.progress = (float)totalBytesWritten/totalBytesExpectedToWrite;        //設定成百分比形式    NSString *percent = [NSString stringWithFormat:@"下載進度 %0.0f%%", (double)totalBytesWritten/totalBytesExpectedToWrite*100];    self.progressLabel.text = percent;}

其中一些點要注意下:
一、
UIProgressView的progress為float型,所以設定時也要為float型,否則不顯示動畫效果

self.progressView.progress = (float)totalBytesWritten/totalBytesExpectedToWrite;

效果而下:

沒有強制轉換

self.progressView.progress = totalBytesWritten/totalBytesExpectedToWrite;

效果而下:

二、
NSSearchPathForDirectoriesInDomains可以用來擷取app的私人檔案路徑,即沙箱中的資料夾清單,擷取的為數組形式。

//擷取Document檔案夾NSString *document = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];//擷取Cache檔案夾NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];

 

IOS斷點下載

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.