POSTリクエストを使用して、サーバーから大きなファイルをダウンロードしようとしています。ファイルはbase64Encodedデータとして受信されます。ファイルサイズは400Mbを超えています。私が使用した最初のアプローチは、受信データとその後にconnectionDidFinishLoading私はデコードを使用して、データを文書ディレクトリにファイルに書き込むデータを追加することでした。この方法は、サイズの小さいファイルに対して有効です。しかし、ファイルサイズが非常に大きい(400MB)のでクラッシュします。その後、NSFileHandleのアプローチを使用して、データが受信されたときにチャンクにファイルを書き込みました。私は3MBのチャンクを使ってデータを書きました。 3MBより小さいファイルの場合、受信したデータはbase64から直接デコードされ、ファイルは正常に作成されます。しかし、ファイルサイズが3MBを超えると、 "initWithBase64EncodedData:Option"を使用してbase64からチャンクデータをデコードしようとすると、取得するデータはゼロになります。私がコードで間違っていることを知りたいですか?NsurlConnectionを使用して大きなbase64エンコードデータをダウンロードする
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response
{
receivedData = [[NSMutableData alloc] init];
NSString* folderPath = [NSHomeDirectory() stringByAppendingPathComponent:@"/Documents/UserDocs"];
if(![[NSFileManager defaultManager] fileExistsAtPath:folderPath]) {
[[NSFileManager defaultManager] createDirectoryAtPath:folderPath withIntermediateDirectories:NO attributes:nil error:nil];
}
NSString *strFilePath = [folderPath stringByAppendingPathComponent:strFileName]; NSString *newFilePath = [NSString stringWithFormat:@"%@.%@", strFilePath, strFileExtension];
if(![[NSFileManager defaultManager] fileExistsAtPath:newFilePath]) {
[[NSFileManager defaultManager] createFileAtPath:newFilePath contents:nil attributes:nil];
}
self.fileHandle = [[NSFileHandle fileHandleForWritingAtPath:newFilePath] retain];
[self.fileHandle seekToFileOffset:0];
}
- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
{
[receivedData appendData:data];
NSUInteger chunkSize = 300000;
if(receivedData.length > chunkSize && self.fileHandle!=nil) {
NSData *chunk = [receivedData subdataWithRange:NSMakeRange(0, chunkSize)];
NSData *writableData = [[NSData alloc] initWithBase64EncodedData:chunk options:NSDataBase64DecodingIgnoreUnknownCharacters];
[receivedData replaceBytesInRange:NSMakeRange(0, chunkSize) withBytes:NULL length:0];
[self.fileHandle seekToEndOfFile];
[self.fileHandle writeData:writableData];
[writableData release];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{
if (receivedData)
{
NSData *writableData = [[NSData alloc] initWithBase64EncodedData:receivedData options:NSDataBase64DecodingIgnoreUnknownCharacters];
[receivedData release];
[self.fileHandle seekToEndOfFile];
[self.fileHandle writeData:writableData];
[writableData release];
NSLog(@"File Write Success!!");
}
}
Base64は1対1エンコード方式ではありません。したがって、現在のチャンク*で必要とされている以前の*チャンク*のデータがあります。いくつかの形式のbase-64ストリームデコーダを使用する可能性を調べる必要があります。ここで入力データの塊を送り、デコードされたデータをどこに書き込むかを教えてください。 – trojanfoe
NSStream、データファイルのストリームを試して、オンザフライでデコード/エンコードして1つのバイナリを作成してください。コードで動作すれば教えてください:) –
サーバーを制御していますか?もしそうなら、base64エンコーディングをせずにそのままの状態でデータを送信するのはなぜですか?たとえば、大規模なブロブを超えて追加のデータを返送する必要がある場合は、マルチパートMIME応答を使用できます。または、メタデータを最初に提供し、2番目のリクエストでエンコードされていない大きなデータファイルを要求できるURLを指定します。 – dgatwood