3

我正在开发一个 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,但无法打开它。

有人知道任何线索吗?

4

3 回答 3

1

我已经为流 ALAsset 对象制作了 NSInputStream 实现 - POSInputStreamLibrary。它不会将整个 1GB 视频读入内存作为您的解决方案,而是读取带有块的电影。当然这不是 POSBlobInputStream 的唯一特性。更多信息在我的 GitHub 存储库中。

于 2014-03-15T09:48:32.963 回答
0

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

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

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

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

于 2013-01-31T08:56:16.183 回答
0

首先,我想您的意思是通过转换ALAssetNSInputStream其他方式来减少内存容量NSData。但是您NSData先将其转换为,然后再转换NSDataNSInputStream,这没有意义,也不会减少内存容量,因为您已经将视频放入内存与NSData

因此,如果您想通过传输视频Stream以减少内存压力(或者您别无选择,因为您的视频高达 2GB 或更多),您应该使用CFStreamCreateBoundPair逐块上传文件,请参阅下面编写的Apple iOS 开发人员库.

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

我在githubALAsset上有一个转换为NSInputStreamvia的 swift 版本。关键点就像编写的文档一样。另一个参考是这个问题CFStreamCreateBoundPair

希望对您有所帮助。

于 2016-05-30T02:11:02.777 回答