【问题标题】:Upload video to FTP from iDevice从 iDevice 上传视频到 FTP
【发布时间】:2012-10-22 06:51:52
【问题描述】:

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

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

quicktime player返回的错误信息是“无法打开,因为无法识别电影的文件格式”

在我的代码中,我让用户使用 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,但无法打开。

有人知道吗?

【问题讨论】:

    标签: iphone objective-c ipad ftp nsinputstream


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

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

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

      【讨论】:

        【解决方案3】:

        首先,我猜你的意思是通过将ALAsset 转换为NSInputStream 而不是NSData 来减少内存容量。但是你先将它转换为NSData 然后再转换NSData 你必须要NSInputStream ,这没有意义,也不会减少内存容量,因为您已经使用NSData 将视频放入内存。

        所以如果你想通过Stream传输你的视频以减少内存压力(或者你没有选择,因为你的视频高达2GB或更多),你应该使用CFStreamCreateBoundPair逐块上传文件,见下面写的Apple iOS Developer Library

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

        我有一个在github 中通过CFStreamCreateBoundPairALAsset 转换为NSInputStream 的快捷版本。关键点就像编写的文档一样。另一个参考是this question

        希望对你有所帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-10-02
          • 1970-01-01
          • 1970-01-01
          • 2017-06-19
          相关资源
          最近更新 更多