[英]Downloading a large file in iOS app
我正在嘗試清理一些現有的代碼,這些代碼從服務器中以塊的形式下載大文件,檢查每個50個數據包的校驗和,然后將它們拼接在一起。 我有一些麻煩,看看它是否是最有效的方式,因為內存問題,它現在崩潰了一段時間。 如果我沒有校驗和,它似乎沒有崩潰,但我希望我能先檢查我的文件。
@property (nonatomic, retain) NSMutableData * ReceivedData;
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSData *sequencePacketData = [[NSData alloc] initWithData:self.ReceivedData];
[self ProcessPacket:sequencePacketData];
[sequencePacketData release];
[[NSNotificationCenter defaultCenter] postNotificationName:DownloadNotification object:self];
}
- (void)ProcessPacket:(NSData *)sequencePacketData {
// find the directory I need to write to and the name of the file
NSString *currentChecksum = [WebServiceManager MD5CheckSumForNSData:sequencePacketData];
BOOL checkSumValid = [dmgr ValidateChecksum:currentChecksum againstFileName:self.CurrentFileName];
self.IsSuccessful = checkSumValid;
if (!checkSumValid) {
// log error msg
return;
}
if (success)
{
NSFileHandle *handle = [NSFileHandle fileHandleForUpdatingAtPath:sequencePath];
[handle seekToEndOfFile];
[handle writeData:sequencePacketData];
[handle closeFile];
}
else
{
[sequencePacketData writeToFile:sequencePath atomically:YES];
}
// When file is completely downloaded, check the checksum of the entire file:
BOOL completeFileCheckSum;
if ([packetFile isEqualToString:@"50.bin"]) {
NSData *temData = [NSData dataWithContentsOfFile:sequencePath];
currentChecksum = [WebServiceManager MD5CheckSumForNSData:temData];
completeFileCheckSum = [dmgr ValidateChecksum:currentChecksum againstFileName:fileName];
NSLog(@"Checksum for whole file is valid: %i", completeFileCheckSum);
if (!completeFileCheckSum) {
NSError *err;
[fileManager removeItemAtPath:sequencePath error:&err];
// log error
return;
}
}
}
+ (NSString*)MD5CheckSumForNSData:(NSData *) input
{
// Create byte array of unsigned chars
unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH];
// Create 16 byte MD5 hash value, store in buffer
CC_MD5(input.bytes, input.length, md5Buffer);
// Convert unsigned char buffer to NSString of hex values
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[output appendFormat:@"%02x",md5Buffer[i]];
return output;
}
檢查校驗和againstFile方法只是從臨時文件中獲取校驗和並進行比較。
我讀到了關於NSAutoReleasePools以及如果你正在加載一堆圖像並且需要清除內存等,這有什么用呢,但是我不確定這是否真的適用於此,如果那樣,或者其他什么可以幫助下載大文件(略小於1 GB)。 謝謝!
將這么多數據保存在內存中肯定會成為一個問題。 幸運的是,您不需要 - 您可以將數據寫入磁盤,並且可以保持運行的校驗和。
將您的ReceivedData換成幾個新的ivars:
NSFileHandle* filehandle;
MD5_CTX md5sum;
MD5_CTX在OpenSSL中,哪個......還不在iOS上? 嘎。 好的,您可以在線找到MD5源代碼,例如: http : //people.csail.mit.edu/rivest/Md5.c (我最初建議將OpenSSL添加到您的項目中,但這是很多額外的垃圾郵件你不需要。但如果你碰巧已經在使用OpenSSL,那么它包含了MD5功能。)
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response
{
MD5Init(&md5sum);
filehandle = [[NSFileHandle filehandleForWritingAtPath:path] retain];
}
- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
{
MD5Update(&md5sum, [data bytes], [data length]);
[filehandle writeData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{
MD5Final(&md5sum);
// MD5 sum is in md5sum.digest[]
[filehandle closeFile];
// verify MD5 sum, etc..
}
最后,你的文件將在磁盤上,你將擁有它的MD5總和,你幾乎不會使用任何內存。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.