Search code examples
objective-ccocoaftpasyncfileuploadcocoaasyncsocket

How to transfer large files/directories over network using AsyncSocket


I've tried the NSTask > NSData method, but the CPU/memory overhead is extremely large for anything over 1GB, so I need to find a way to do this like, say, an FTP server does it.

EDIT: How does remote desktop's copy files do it?


Solution

  • I think I got it. I had to read it into the memory in small byte-size (HAHA GET THE PUN?) pieces and transfer it over that way. Keep in mind that this only works for files, not directories. I tested it on a 450MB file and it copied in about 3 minutes with the exact same byte count as the source. It was a video, and while I was streaming it to the client, I was able to play it as well. Nifty, huh?

    Without further ado, here's the code I used, slightly patched up to do a simple file-copy instead of over the network.

    [[NSFileManager defaultManager] createFileAtPath:@"/path/to/file/dest" contents:nil attributes:nil];
    NSFileHandle *output = [NSFileHandle fileHandleForWritingAtPath:@"/path/to/file/dest"];
    
    uint64 offset = 0;
    uint32 chunkSize = 8192;
    
    
    NSFileHandle *handle = [NSFileHandle fileHandleForReadingAtPath:@"/path/to/file/source"];
    NSAutoreleasePool *autoreleasePool = [[NSAutoreleasePool alloc] init];
    NSData *data = [handle readDataOfLength:chunkSize];
    
    NSLog(@"Entering Loop.");
    
    while ([data length] > 0) {
        [output seekToEndOfFile];
        [output writeData:data];
        offset += [data length];
    
        NSLog(@"Switching Loop.");
    
        [autoreleasePool release];
        autoreleasePool = [[NSAutoreleasePool alloc] init];
    
        [handle seekToFileOffset:offset];
        data = [handle readDataOfLength:chunkSize];
    }
    
    NSLog(@"Exited Loop.");
    
    [handle closeFile];
    [autoreleasePool release];
    
    [output closeFile];
    [output release];