-->

How to Transfer Large Files over wifi in iOS

2020-06-09 07:02发布

问题:

I downloaded WiTap Code From Apple's website. Its for transferring data over local wifi network. I am working in a project to interact as client - server architecture. I am sending NSData from client side to server.

I made 2 projects; one for client and one for server

At client side project, i made following Changes For that I modified the AppController.m file by adding following method

AppController.m (Client side)

- (void)sendData:(NSData*)pobjData
{
    assert(self.streamOpenCount == 2);

    if ( [self.outputStream hasSpaceAvailable] ) 
    {
        NSInteger   bytesWritten;

        NSUInteger length = [pobjData length];

        bytesWritten = [self.outputStream write:[pobjData bytes] maxLength:[pobjData length]];

        NSLog(@"written bytes -> %d",bytesWritten);
    }
}

Then by calling this method I send data.

At Server side project, I made following chagnes for that I modified the AppController.m file by modifying following method

AppController.m (Server side)

- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
{
    #pragma unused(stream)

    switch(eventCode) {

        case NSStreamEventOpenCompleted: {
            self.streamOpenCount += 1;
            assert(self.streamOpenCount <= 2);

            // Once both streams are open we hide the picker and the game is on.

            if (self.streamOpenCount == 2) {
                [self dismissPicker];

                [self.server deregister];
            }
        } break;

        case NSStreamEventHasSpaceAvailable: {
            assert(stream == self.outputStream);
            // do nothing
        } break;

        case NSStreamEventHasBytesAvailable:
        {
            if (stream == self.inputStream)
            {

                NSInteger bytesRead;
                uint32_t buffer[32768];

                NSMutableData *_data = [NSMutableData data];

                // Pull some data off the network.
                bytesRead = [self.inputStream read:buffer maxLength:sizeof(buffer)];
                if (bytesRead == -1) {

                } else if (bytesRead == 0) {

                } else {
                    // FIXME: Popup an alert

                    const long long expectedContentLength = bytesRead;
                    NSUInteger expectedSize = 0;

                    // expectedContentLength can be represented as NSUInteger, so cast it:
                    expectedSize = (NSUInteger)expectedContentLength;

                    [_data appendBytes:buffer length:expectedSize];

                    NSLog(@"\"Data received has length: %d", _data.length);

                    [self performSelector:@selector(getData:) withObject:_data afterDelay:1.0];
                }
            }
        }
            break;

        default:
            assert(NO);
            // fall through
        case NSStreamEventErrorOccurred:
            // fall through
        case NSStreamEventEndEncountered: {
            [self setupForNewGame];
        } break;
    }
}

and added a method to write the received data as a file

     #define kUserDirectoryPath NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)

-(void)getData:(NSMutableData *)pData
{
                NSFileManager *tmpmanager = [NSFileManager defaultManager];
                [tmpmanager createFileAtPath:[AppController getDocumentDirectoryPath:[NSString stringWithFormat:@"%@.png",[NSDate date]]] contents:pData attributes:nil];
}


+(NSString*)getDocumentDirectoryPath:(NSString*)pStrPathName
{
            NSString *strPath=nil;

            if(pStrPathName)
                strPath = [[kUserDirectoryPath objectAtIndex:0] stringByAppendingPathComponent:pStrPathName];

            return strPath;
}

I convert .png files to NSData and send them from client side to server side. the server downloads the file to Document Directory

The matter is , when i transfer file from client side , it gets downloaded to server side at document directory. Everything works fine in case of tiny files. If file size exceeds to 8kB , file written at document directory gets corrupted.

Kindly help me to be able to send large files.

回答1:

The problem is that your code doesn't loop to gather all of the available data till the end (or loop to send all data either). So you only ever receive the first buffer of data. If the image is small then that works ok, if the image is bigger then it never will.

You need to write the code so that it keeps sending when there is buffer space until all data is sent and keep reading data (into an NSMutableData instance variable, not a local variable) until the end of the stream is reached.



回答2:

You can use AsyncSocket which can be downloaded from

https://github.com/roustem/AsyncSocket ,

this is an objective-c wrapper build on CFSocket and CFNetwork, it can handle large amount of data transfer with TCP/UDP protocol on local wifi.

You can find the wiki here https://github.com/darkseed/cocoaasyncsocket/wiki/iPhone

The class is very simple and easy to implement.Give it a try



回答3:

You have make a web service from where you need to put IP address of the system, Where you want to send the file and after that when you can connected with the entered IP address you can send the file in Base64 and NSData format.