Iphone Objective-C检查下载的文件大小

Iphone Objective-C检查下载的文件大小,iphone,objective-c,download,Iphone,Objective C,Download,我正在创建一个从S3服务器下载.zip文件的应用程序。 一切正常。现在我想能够中断当前的下载。如果我可以保存文件的当前大小(字节),我将能够发送一个新的请求,其中包含文件其他部分的范围标头 问题在于,我无法确定“已”下载内容的大小,因为只有在下载完成后,我才能看到目录中的文件。因此,如果我中断,则不会保存部分文件 此时,我使用以下代码进行此操作: -(void) downloadFile:(NSMutableArray*)paramArray withDict:(NSMutableDictio

我正在创建一个从S3服务器下载.zip文件的应用程序。 一切正常。现在我想能够中断当前的下载。如果我可以保存文件的当前大小(字节),我将能够发送一个新的请求,其中包含文件其他部分的范围标头

问题在于,我无法确定“已”下载内容的大小,因为只有在下载完成后,我才能看到目录中的文件。因此,如果我中断,则不会保存部分文件

此时,我使用以下代码进行此操作:

 -(void) downloadFile:(NSMutableArray*)paramArray withDict:(NSMutableDictionary*)options
 {

NSLog(@"DOWNLOAD THREAD STARTED");
NSString * sourceUrl = [paramArray objectAtIndex:0];
NSString * fileName = [paramArray objectAtIndex:1];

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];    

NSString *newFilePath = [documentsDirectory stringByAppendingString:fileName];

NSError *error=[[[NSError alloc]init] autorelease]; 


NSURLConnection *fileURL = [NSData dataWithContentsOfURL: [NSURL URLWithString:sourceUrl]];

BOOL response = [fileURL writeToFile:newFilePath options:NSDataWritingFileProtectionNone error:&error]; 

if (response == TRUE)
{
    NSLog(@"DOWNLOAD COMPLETED");
    [self performSelectorOnMainThread:@selector(downloadComplete:withDict:) withObject:paramArray waitUntilDone:YES];
}
else 
{
    NSLog(@"Something went wrong while downloading file.");
    NSString *callback = [NSString stringWithFormat:@"downloadInterrupted('%@');",fileName];
    [webView stringByEvaluatingJavaScriptFromString:callback];

}

[pool drain];
}

AsiHTTP不是一个选项,因为我使用的PhoneGap存在问题。

您将不得不使用较低级别的api

是时候阅读unix套接字编程了。这将是一个良好的开端


这真的不会太难。诚实。

更好的办法是异步下载文件。这有几个优点:最重要的一个是您的用户界面保持快速响应。用户可以在下载和等待数据时继续使用您的应用程序。如果您正在下载的数据对应用程序绝对重要,请显示某种加载指示器

您可以通过以下方式轻松启动异步下载:

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:sourceUrl]];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
现在,如何获取
NSData
对象中的下载数据?您为
self
实现以下委托方法:

-connection:didReceiveData:
-connection:didFailWithError:
-connectionDidFinishLoading:
这样做的目的是,当某些数据通过您的连接进入或发生任何其他重要事件(例如成功或失败)时,都会通知您。因此,您将声明一个临时的
NSMutableData
对象作为实例变量(比如
downloadData
),并对其进行写入,直到下载完成。不要忘记初始化空对象并声明属性

-connection:didReceiveData:
在某种数据(即下载文件的一部分)到达时被调用。因此,您要将其附加到临时对象,如下所示:

-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [self.downloadData appendData:data];
}
下载完成(成功)后,将调用下一个委托方法:

-(void) connectionDidFinishLoading:(NSURLConnection *)connection {
    //do whatever you need to do with the data in self.downloadData
}

如果下载失败,则调用
-connection:didFailWithError:
。然后,您可以保存临时对象,获取其大小,然后继续下载<代码>[self.downloaddatalength]获取对象中数据的大小(以字节为单位)

我建议您构建一种方法,每1、2MB或更少的时间保存一次数据块,以便正确恢复下载并避免内存崩溃。 这是因为如果在传输过程中出现错误,可能会导致文件损坏

无论如何,发送一个范围HTML头是非常简单的

NSFileHandle *fileHandler = [NSFileHandle fileHandleForReadingAtPath:dataPreviouslySavedPath];
[fileHandler seekToEndOfFile];
unsigned long long int range = [fileHandler offsetInFile];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:downloadURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.0];
[request setValue:[NSString stringWithFormat:@"bytes=%lli-", range] forHTTPHeaderField:@"Range"];

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

希望这对你有所帮助。

你到底为什么这样做:
NSURLConnection*fileURL=[NSData dataWithContentsOfURL:[NSURL URLWithString:sourceUrl]]?您正在将
NSData
对象分配给
NSURLConnection
变量。你没有收到警告吗?这看起来很清楚!我马上就开始。提前感谢。如果下载失败,则调用的是
-connection:didfailwitheror:
,而不是
-connectiondifinishload:
。正确的套接字编程很困难。在那里呆了很长时间,做了很长时间。比约恩的建议是,在Objective-C世界中有更好的选择。但如果您想获得较低的级别,请查看为您提供runloop支持的
NSFileHandle