iOS 文件下載到本地、緩存 、斷點續傳

由於項目需要下載一些文件,結合以前寫的圖片緩存:http://blog.csdn.net/marujunyy/article/details/8538679

用ASIHttpRequest 封裝了一個文件下載類:支持斷點續傳、緩存到Document文件夾。


使用方法:

在.h文件裏  #import"AsyncFileBuffer.h" 並添加代理:AsyncFileDelegate

    AsyncFileBuffer *asyncBuffer = [[AsyncFileBuffer alloc] init]; 
    asyncBuffer.delegate = self;
    [asyncBuffer loadFileFromURLString:@"http://file.easymorse.com/app/sxhm/RemoteNotificationsPG.pdf"];

#pragma mark - AsyncFileDelegate
- (void)asyncBufferSuccess:(AsyncFileBuffer *)buffer fileLocationPath:(NSString *)locPath
{
    //locPath 下載的文件在本地的路徑
}
- (void)asyncBuffer:(AsyncFileBuffer *)buffer progress:(float)progress fileSize:(uint)fileSize rate:(NSString *)rate
{
    //下載進度:如果已下載到本地 該方法不會被調用
    NSString *downSize = [buffer formatFileSize:fileSize*progress];
    NSLog(@"已下載:%@  文件大小:%@",downSize,[buffer formatFileSize:fileSize]);
    NSLog(@"進度:%.2f%%  下載速度:%@",progress*100,rate);
}
- (void)asyncBufferFailed:(AsyncFileBuffer *)buffer
{ 
    NSLog(@"error : %@",buffer.error);
}


AsyncFileBuffer.h

//
//  AsyncFileBuffer.h 
//
//  Created by marujun on 13-9-8.
//  Copyright (c) 2013年 極致. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "ASIFormDataRequest.h"

@class AsyncFileBuffer;

@protocol AsyncFileDelegate <NSObject> 
- (void)asyncBuffer:(AsyncFileBuffer *)buffer progress:(float)progress fileSize:(uint)fileSize rate:(NSString *)rate;
- (void)asyncBufferSuccess:(AsyncFileBuffer *)buffer fileLocationPath:(NSString *)locPath;
- (void)asyncBufferFailed:(AsyncFileBuffer *)buffer;

@end

@interface AsyncFileBuffer : NSObject<ASIHTTPRequestDelegate>
{ 
    __block uint fileSize; //以B爲單位,文件大小
    __block uint completedSize; //已下載文件的大小
    NSDate *startTime;
}

@property (nonatomic,assign) int tag;
@property (nonatomic,retain) id<AsyncFileDelegate> delegate;
@property (nonatomic,retain) NSURL *downloadURL;
@property (nonatomic,retain) NSString *originalUrlString; //未做處理的url字符串
@property (nonatomic,retain) ASIHTTPRequest *request;
@property (nonatomic,retain) NSError *error;

- (void)loadFileFromURLString:(NSString *)urlStr;

- (void)pauseDownload;      //暫停下載
- (void)resumeDownload;   //繼續下載
- (NSString *)formatFileSize:(unsigned long long)size; //轉換B爲K、M、G、T

@end

AsyncFileBuffer.m

//
//  AsyncFileBuffer.m 
//
//  Created by marujun on 13-9-8.
//  Copyright (c) 2013年 極致. All rights reserved.
//

#import "AsyncFileBuffer.h"

@implementation AsyncFileBuffer
@synthesize request = _request;
@synthesize error = _error;
@synthesize delegate = _delegate;
@synthesize downloadURL = _downloadURL;
@synthesize originalUrlString = _originalUrlString;
@synthesize tag = _tag;

- (void)dealloc
{
    [_error release];
    [_request release];
    [_delegate release];
    [super dealloc]; 
}

- (void)loadFileFromURLString:(NSString *)urlStr
{
    self.originalUrlString = urlStr;
    _downloadURL = [NSURL URLWithString:[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    if(_downloadURL!=nil&&![_downloadURL isEqual:@""]) {
        if ([self isExistsFile:[_downloadURL description]]) {
            //返回數據 
            if ([self.delegate respondsToSelector:@selector(asyncBufferSuccess:fileLocationPath:)]) {
                [self.delegate asyncBufferSuccess:self fileLocationPath:[self getFilePathWithURL:[_downloadURL description]]];
            }
        }else{
            [self retain];
            [self createDirectoryWithUrl:_downloadURL];
            [self resumeDownload];
        }
    }
} 

- (void)pauseDownload
{ 
    [_request clearDelegatesAndCancel]; 
}
- (void)resumeDownload
{ 
    NSString *downloadPath = [self getFilePathWithURL:[_downloadURL description]]; 
    _request = [[ASIHTTPRequest alloc] initWithURL:_downloadURL];
    _request.downloadDestinationPath = [self getFilePathWithURL:[_downloadURL description]]; //現在下載文件路徑
    _request.temporaryFileDownloadPath = [downloadPath stringByAppendingString:@".temp"]; //臨時路徑
    _request.allowResumeForFileDownloads = YES; //設置支持斷點續傳
    _request.downloadProgressDelegate = self; //進度顯示
    _request.delegate = self;
    [_request startAsynchronous];
}

- (void)createDirectoryWithUrl:(NSURL *)url
{
    fileSize = 0;
    //如果不存在則創建,因爲asi下載時,不會自動創建文件夾
    NSFileManager *fileManager = [NSFileManager defaultManager]; 
    NSString *folderPath = [self getFilePathWithURL:[url description]];
    
    NSRange range = [folderPath rangeOfString:@"/" options:NSBackwardsSearch]; 
    folderPath = [folderPath substringToIndex:range.location]; 
	BOOL fileExists = [fileManager fileExistsAtPath:folderPath]; 
    if (!fileExists) { 
		[fileManager createDirectoryAtPath:folderPath  withIntermediateDirectories:YES attributes:nil error:nil];
	}
}
#pragma mark - ASIHTTPRequestDelegate
- (void)requestStarted:(ASIHTTPRequest *)request
{
    startTime = [[NSDate date] retain];
    completedSize = 0.0;
}
- (void)request:(ASIHTTPRequest *)request didReceiveResponseHeaders:(NSDictionary *)responseHeaders
{
    fileSize = request.contentLength; 
//    fileSize = [[responseHeaders valueForKey:@"Content-Length"] floatValue];
}
- (void)setProgress:(float)newProgress
{
    double deltaTime = [[NSDate date] timeIntervalSinceDate:startTime];
    double downSize = (newProgress*fileSize-completedSize)/deltaTime;
    NSString *rate = [NSString stringWithFormat:@"%@/S",[self formatFileSize:downSize]];
    completedSize = newProgress*fileSize;
    startTime = [[NSDate date] retain]; 
    
    if ([self.delegate respondsToSelector:@selector(asyncBuffer:progress:fileSize:rate:)]) {
        [self.delegate asyncBuffer:self progress:newProgress fileSize:fileSize rate:rate];
    }
}

-(void)requestFailed:(ASIHTTPRequest *)request
{
//    NSLog(@"requestFailed error %@",request.error);
    self.error = request.error;
    if ([self.delegate respondsToSelector:@selector(asyncBufferFailed:)]) {
        [self.delegate asyncBufferFailed:self];
    } 
    [self release];
}
- (void)requestFinished:(ASIHTTPRequest *)request
{   
    if ([self isExistsFile:[_downloadURL description]]) { 
        if ([self.delegate respondsToSelector:@selector(asyncBufferSuccess:fileLocationPath:)]) {
            [self.delegate asyncBufferSuccess:self fileLocationPath:[self getFilePathWithURL:[_downloadURL description]]];
        }
    }else{
        self.error = [[NSError alloc]initWithDomain:@"AsyncFileBuffer" code:1211 userInfo:[[NSDictionary alloc] initWithObjectsAndKeys:@"下載的文件不存在!",NSLocalizedDescriptionKey, nil]];
        if ([self.delegate respondsToSelector:@selector(asyncBufferFailed:)]) {
            [self.delegate asyncBufferFailed:self];
        }
    }
    [self release];
}

- (BOOL)isExistsFile:(NSString *)fileURL
{
    NSFileManager *filemanage = [NSFileManager defaultManager];
    NSArray *array=[fileURL componentsSeparatedByString:@"//"]; 
    return [filemanage fileExistsAtPath:[self getCacheFilePath:[array lastObject]]];
}

- (NSString *)getFilePathWithURL:(NSString*)fileURL
{ 
    NSArray *array=[fileURL componentsSeparatedByString:@"//"];  
    return [self getCacheFilePath:[array lastObject]];
}

- (NSString *)getCacheFilePath:(NSString *)filename
{
    filename = [NSString stringWithFormat:@"BufferedFile/%@",filename];
    NSString *documentDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; 
	NSString *filePath = [documentDir stringByAppendingPathComponent:filename];
	return filePath;
} 

- (NSString *)formatFileSize:(unsigned long long)size
{
    NSString *formattedStr = nil;
    if (size == 0){
        formattedStr = @"0 B";
    }else if (size > 0 && size < 1024){
        formattedStr = [NSString stringWithFormat:@"%qu B", size];
    }else if (size >= 1024 && size < pow(1024, 2)){
        formattedStr = [NSString stringWithFormat:@"%.1f KB", (size / 1024.)];
    }else if (size >= pow(1024, 2) && size < pow(1024, 3)){
        formattedStr = [NSString stringWithFormat:@"%.2f MB", (size / pow(1024, 2))];
    }else if (size >= pow(1024, 3) && size < pow(1024, 4)){
        formattedStr = [NSString stringWithFormat:@"%.3f GB", (size / pow(1024, 3))];
    }else if (size >= pow(1024, 4)){
        formattedStr = [NSString stringWithFormat:@"%.4f TB", (size / pow(1024, 4))];
    }
    return formattedStr; 
}


@end



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章