我正在尝试使用 POST 请求从服务器下载大文件。该文件作为 base64Encoded 数据接收。文件大小超过400Mb。我使用的第一种方法是附加在 didReceiveData 中接收的数据,然后在 connectionDidFinishLoading 中附加我用于解码数据并写入数据到文件目录中的文件。此方法适用于小尺寸的文件。但它崩溃,因为文件大小非常大(400MB)。然后我使用NSFileHandle的方法在接收数据时以块的形式写入文件。我用3MB的块来写数据。对于小于3MB的文件,从base64直接解码接收的数据,并成功创建文件。但是当文件大小超过3MB并且我尝试使用“ initWithBase64EncodedData:Options ”从base64解码块数据时,我得到的数据是nil。想知道我在代码中做错了什么。
- (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!!");
}
}
答案 0 :(得分:0)
两种可能的方法:
基本上:
#include <sys/stat.h>
#include <sys/mman.h>
...
NSURL *url = // path to file on disk
char *path = [url fileSystemRepresentation];
struct stat buf;
// Round up to an exact multiple of the page size
NSUInteger size = (buf.st_size + PAGE_MASK) & ~PAGE_MASK;
NSData *data = nil;
if (!stat(path, &buf)) {
int fd = open(path, O_RDONLY);
if (fd != -1) {
mmap(NULL, size, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0);
data = [NSData dataWithBytesNoCopy:buf length:buf.st_size];
}
}
// Perform a base64 decode on the NSData object and hope that
// at least the result will fit in RAM.
// Clean up.
data = nil;
if (!stat(path, &buf)) {
int fd = open(path, O_RDONLY);
if (fd != -1) {
munmap(addr, size);
}
}
创建可以将数据直接写入磁盘上文件的base64解码器留给读者练习。 : - )