从iDevice将视频上传到FTP

时间:2012-10-22 06:51:52

标签: iphone objective-c ipad ftp nsinputstream

我正在开发一个APP,供用户将视频上传到我们的FTP服务器

到目前为止,一切都已基本完成但我遇到一个问题是用户上传视频(.MOV)后,我无法打开并播放文件。

quicktime播放器返回的错误消息是“因电影的文件格式无法识别而无法打开”

在我的代码中,我让用户使用ALAssetsLibrady

选择视频

然后将视频加载到ALAsset对象中,在开始上传之前,将视频从ALAsset加载到NSInputStream对象中,这是代码。

ALAssetRepresentation *rep = [currentAsset defaultRepresentation];
Byte *buffer = (Byte*)malloc(rep.size);
NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:rep.size error:nil];
NSData *data = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];

iStream = [NSInputStream inputStreamWithData:data];
[iStream open];

下一步是设置NSOutputStream并打开它,通过以下代码处理上传操作。

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
switch (eventCode) {
    case NSStreamEventNone:
    {
        break;
    }
    case NSStreamEventOpenCompleted:
    {
        //opened connection
        NSLog(@"opened connection");
        break;
    }
    case NSStreamEventHasBytesAvailable:
    {
        // should never happen for the output stream
        [self stopSendWithStatus:@"should never happen for the output stream"];
        break;
    }
    case NSStreamEventHasSpaceAvailable:
    {
        // If we don't have any data buffered, go read the next chunk of data.
        NSInteger bufferSize = 65535;
        uint8_t *buffer = malloc(bufferSize);

        if (bufferOffset == bufferLimit) {
            NSInteger bytesRead = [iStream read:buffer maxLength:bufferSize];

            if (bytesRead == -1) {
                [self stopSendWithStatus:@"file read error"];
            } else if (bytesRead == 0) {
                [self stopSendWithStatus:nil];
            } else {
                bufferOffset = 0;
                bufferLimit  = bytesRead;
            }
        }

        // If we're not out of data completely, send the next chunk.

        if (bufferOffset != bufferLimit) {
            NSInteger bytesWritten = [oStream write:&buffer[bufferOffset] maxLength:bufferLimit - bufferOffset];
            if (bytesWritten == -1) {
                [self stopSendWithStatus:@"file write error"];
            } else {
                bufferOffset += bytesWritten;
            }
        }

        //NSLog(@"available");
        break;
    }
    case NSStreamEventErrorOccurred:
    {
        //stream open error
        [self stopSendWithStatus:[[aStream streamError] description]];
        break;
    }
    case NSStreamEventEndEncountered:   //ignore
        NSLog(@"end");
        break;
}
}

没有任何错误发生,视频文件确实上传到FTP文件大小和名称正确,但无法打开它。

有人知道任何线索吗?

3 个答案:

答案 0 :(得分:1)

我为流式ALAsset对象制作了NSInputStream实现 - POSInputStreamLibrary。它不会将整个1GB视频作为您的解决方案读入内存,而是使用块来读取电影。当然,这不是POSBlobInputStream的唯一功能。更多关于我的GitHub存储库的信息。

答案 1 :(得分:0)

我知道这可能不是您正在寻找的答案,但您不应该通过FTP使用直接连接来允许用户将文件上传到您的网络服务器。与REST相比,这是不安全和缓慢的。

相反,为什么不写一点点的PHP来处理上传,并通过REST从应用程序发布文件?这里:

$uploaddir = 'uploads/';
$file = basename($_FILES['file']['name']);
$uploadfile = $uploaddir . $file;

我还建议使用AFNetworking来处理POST请求http://afnetworking.com/

答案 2 :(得分:0)

首先,我想您的意思是通过将ALAsset转换为NSInputStream而不是NSData来减少内存容量。但是您先将其转换为NSData然后转换为NSData {1}}您必须NSInputStream,它没有意义,并且不会因为NSData已将视频放入内存而无法降低内存容量。

因此,如果您想通过Stream传输视频以减少内存压力(或者您没有选择,因为您的视频最高可达2GB或更多),则应使用CFStreamCreateBoundPair上传按块查看文件块,请参阅下面的Apple iOS Developer Library

  

对于大块构造数据,调用CFStreamCreateBoundPair创建一对流,然后调用setHTTPBodyStream:方法告诉NSMutableURLRequest使用其中一个流作为其主体内容的源。通过写入另一个流,您可以一次发送一个数据。

我在github中通过ALAsset快速转换NSInputStreamCFStreamCreateBoundPair。关键点就像撰写的文档一样。另一个参考是{{3 }}

希望它对你有所帮助。