如何在iOS中通过wifi传输大文件

时间:2013-04-05 09:04:12

标签: iphone ios bonjour nsstream

我从Apple网站下载了WiTap代码。它用于通过本地wifi网络传输数据。我正在一个项目中作为客户端 - 服务器架构进行交互。我正在从客户端向服务器发送NSData。

我做了两个项目;一个用于客户端,一个用于服务器

在客户端项目中,我进行了以下更改 为此,我通过添加以下方法

修改了 AppController.m 文件

AppController.m (客户端)

- (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);
    }
}

然后通过调用此方法发送数据。

在服务器端项目中,我通过修改以下方法修改了AppController.m文件以下的chagnes

AppController.m (服务器端)

- (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;
    }
}

并添加了一种将接收到的数据写为文件的方法

     #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;
}

我将.png文件转换为NSData并将它们从客户端发送到服务器端。服务器将文件下载到文档目录

问题是,当我从客户端传输文件时,它会被下载到文档目录的服务器端。在文件很小的情况下,一切正常。如果文件大小超过8kB,则在文档目录中写入的文件将被破坏。

请帮我发送大文件。

3 个答案:

答案 0 :(得分:1)

问题是你的代码没有循环来收集所有可用数据直到最后(或循环发送所有数据)。所以你只收到第一个数据缓冲区。如果图像很小则可以正常工作,如果图像较大则永远不会。

您需要编写代码,以便在有缓冲区空间时继续发送,直到发送所有数据并继续读取数据(转换为NSMutableData实例变量,而不是本地变量),直到流结束到了。

答案 1 :(得分:0)

您可以使用可从

下载的AsyncSocket

https://github.com/roustem/AsyncSocket

这是一个基于CFSocket和CFNetwork的Objective-c包装器,它可以在本地wifi上使用TCP / UDP协议处理大量数据传输。

您可以在https://github.com/darkseed/cocoaasyncsocket/wiki/iPhone

找到维基

该课程非常简单,易于实施。试一试

答案 2 :(得分:-1)

您已经建立了一个Web服务,您需要将系统的IP地址,您要发送文件的位置放在哪里,之后当您可以使用输入的IP地址连接时,您可以发送Base64和NSData格式的文件