用iPhone上传视频

时间:2009-06-30 19:47:47

标签: iphone video upload

是否可以将视频上传到服务器?我知道图像是可能的。 如果有人可以指出我正确的方向,那将是非常棒的。

由于

4 个答案:

答案 0 :(得分:17)

2015年8月编辑

这个答案现在已经过时了。在撰写本文时,没有太多选项,视频的尺寸相对较小。 如果您现在正在考虑这样做,我会使用AFNetworking这使得这更简单。它将从文件中流式传输上传而不是将其全部保存在内存中,并且还支持新的Apple后台上传任务。

文档:https://github.com/AFNetworking/AFNetworking#creating-an-upload-task

-

是的,这是可能的,这就是我的方式。

实现以下在媒体选择器完成时运行的功能。

- (NSData *)generatePostDataForData:(NSData *)uploadData
{
    // Generate the post header:
    NSString *post = [NSString stringWithCString:"--AaB03x\r\nContent-Disposition: form-data; name=\"upload[file]\"; filename=\"somefile\"\r\nContent-Type: application/octet-stream\r\nContent-Transfer-Encoding: binary\r\n\r\n" encoding:NSASCIIStringEncoding];

    // Get the post header int ASCII format:
    NSData *postHeaderData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];

    // Generate the mutable data variable:
    NSMutableData *postData = [[NSMutableData alloc] initWithLength:[postHeaderData length] ];
    [postData setData:postHeaderData];

    // Add the image:
    [postData appendData: uploadData];

    // Add the closing boundry:
    [postData appendData: [@"\r\n--AaB03x--" dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]];

    // Return the post data:
    return postData;
}


- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{ 

    //assign the mediatype to a string 
    NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];

    //check the media type string so we can determine if its a video
    if ([mediaType isEqualToString:@"public.movie"]){
        NSLog(@"got a movie");
        NSURL *videoURL = [info objectForKey:UIImagePickerControllerMediaURL];
        NSData *webData = [NSData dataWithContentsOfURL:videoURL];
        [self post:webData];
        [webData release];

    }

对于帖子功能我有这样的东西我从其他地方得到的(对不起,我不知道我在哪里找到它):

- (void)post:(NSData *)fileData
{

    NSLog(@"POSTING");

    // Generate the postdata:
    NSData *postData = [self generatePostDataForData: fileData];
    NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]];

    // Setup the request:
    NSMutableURLRequest *uploadRequest = [[[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.example.com:3000/"] cachePolicy: NSURLRequestReloadIgnoringLocalCacheData timeoutInterval: 30 ] autorelease];
    [uploadRequest setHTTPMethod:@"POST"];
    [uploadRequest setValue:postLength forHTTPHeaderField:@"Content-Length"];
    [uploadRequest setValue:@"multipart/form-data; boundary=AaB03x" forHTTPHeaderField:@"Content-Type"];
    [uploadRequest setHTTPBody:postData];

    // Execute the reqest:
    NSURLConnection *conn=[[NSURLConnection alloc] initWithRequest:uploadRequest delegate:self];
    if (conn)
    {
        // Connection succeeded (even if a 404 or other non-200 range was returned).
        NSLog(@"sucess");
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Got Server Response" message:@"Success" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show];
        [alert release];
    }
    else
    {
        // Connection failed (cannot reach server).
        NSLog(@"fail");
    }

}

上面的代码片段构建了http post请求并提交了它。如果你想要体面的错误处理并考虑使用允许异步上传的库(在github上有一个),你将需要修改它

还要注意上面服务器url上的端口:3000,我发现在开发模式下我可以很容易地在默认端口3000上启动rails服务器进行错误测试,这样我就可以看到用于调试目的的请求参数了

希望这有帮助

答案 1 :(得分:3)

由于iOS8不需要使用第三方库,您可以直接从文件中流式传输视频,当您尝试从文件加载视频时上传更大的视频时,这会解决关键的内存错误:

// If video was returned by UIImagePicker ...
NSURL *videoUrl = [_videoDictionary objectForKey:UIImagePickerControllerMediaURL];

NSMutableURLRequest *request =[[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:VIDEO_UPLOAD_LINK]];
[request addValue:@"video" forHTTPHeaderField: @"Content-Type"];
[request setHTTPMethod:@"POST"];

NSInputStream *inputStream = [[NSInputStream alloc] initWithFileAtPath:[videoUrl path]];
[request setHTTPBodyStream:inputStream];

self.uploadConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];

iOS7还提供了出色的NSURLSeession / NSURLSessionUploadTask组合解决方案,它不仅让您直接从文件中流式传输,而且还可以将任务委派给iOS进程,这样就可以上传完成即使您的应用已关闭。 它需要更多的编码,我没有时间在这里写它(你可以谷歌它)。

以下是最重要的部分:

  1. 在后台支持中配置音频会话:

    - (NSURLSession *)urlSession {

    if (!_urlSession) {
    
    
        NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary];
        NSString *bundleId = infoDict[@"CFBundleIdentifier"];
    
        NSString *label = [NSString stringWithFormat:@"ATLoggerUploadManager_%@", bundleId];
    
        NSURLSessionConfiguration *conf = (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1) ? [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:label] : [NSURLSessionConfiguration backgroundSessionConfiguration:label];
        conf.allowsCellularAccess = NO;
    
        _urlSession = [NSURLSession sessionWithConfiguration:conf delegate:self delegateQueue:self.urlSessionQueue];
        _urlSession.sessionDescription = @"Upload log files";
    
    }
    
    return _urlSession;
    

    }

  2. 上传任务方法:

    - (NSURLSessionUploadTask *)uploadTaskForFilePath:(NSString *)filePath session:(NSURLSession *)session {

    NSFileManager *fm = [NSFileManager defaultManager];
    NSError *error = nil;
    
    // Consruct request:
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setHTTPMethod:@"POST"];
    NSString *finalUrlString = [self.uploadURL absoluteString];
    
    if (self.uploadUserId) {
        [request setValue:self.uploadUserId forHTTPHeaderField:@"X-User-Id"];
        finalUrlString = [finalUrlString stringByAppendingFormat:@"?id=%@", self.uploadUserId];
    }
    
    [request setURL:[NSURL URLWithString:finalUrlString]];
    
    /*
     It looks like this (it only works if you quote the filename):
     Content-Disposition: attachment; filename="fname.ext"
     */
    
    NSString *cdh = [NSString stringWithFormat:@"attachment; filename=\"%@\"", [filePath lastPathComponent]];
    [request setValue:cdh forHTTPHeaderField:@"Content-Disposition"];
    
    error = nil;
    unsigned long fileSize = [[fm attributesOfItemAtPath:filePath error:&error] fileSize];
    
    if (!error) {
    
        NSString *sizeInBytesAsString = [NSString stringWithFormat:@"%lu", fileSize];
        [request setValue:sizeInBytesAsString forHTTPHeaderField:@"X-Content-Length"];
    
    }
    
    NSURL *fileUrl = [NSURL fileURLWithPath:filePath];
    NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromFile:fileUrl];
    uploadTask.taskDescription = filePath;
    
    return uploadTask;
    

    }

  3. 上传功能:

    [self.urlSession getTasksWithCompletionHandler:^(NSArray * dataTasks,NSArray * uploadTasks,NSArray * downloadTasks){

        NSMutableDictionary *tasks = [NSMutableDictionary new];
    
        int resumed_running_count = 0;
        int resumed_not_running_count = 0;
        int new_count = 0;
        // 1/2. Resume scheduled tasks:
        for(NSURLSessionUploadTask *task in uploadTasks) {
    
            //MILogInfo(@"Restored upload task %zu for %@", (unsigned long)task.taskIdentifier, task.originalRequest.URL);
    
            if (task.taskDescription) {
    
                [tasks setObject:task forKey:task.taskDescription];
            }
    
            BOOL isRunning = (task.state == NSURLSessionTaskStateRunning);
            if (!isRunning) {
    
                resumed_not_running_count++;
            }else{
                resumed_running_count++;
            }
    
             [task resume];
        }
    
        // 2/2. Add tasks / files not scheduled yet:
        NSString *uploadFilePath = nil;
    
            // already uploading:
            if (![tasks valueForKey:uploadFilePath]) {
                NSURLSessionUploadTask *uploadTask = [self uploadTaskForFilePath:uploadFilePath session:_urlSession];
                new_count++;
                [uploadTask resume];
            }
    
    }];
    
  4. 后台会话需要UIApplecation委托(实施AppDelegate回调:

    • (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void(^)())completionHandler {

      NSLog(@"Background URL session needs events handled: %@", identifier);
      completionHandler();
      

      }

答案 2 :(得分:2)

看看UIImagePickerController。 从3.0开始,您可以选择拍摄视频或选择现有视频。根据文档,你在电影上限制为最多10分钟:

http://developer.apple.com/IPhone/library/documentation/UIKit/Reference/UIImagePickerController_Class/UIImagePickerController/UIImagePickerController.html

答案 3 :(得分:0)

NSURL *urlvideo = [info objectForKey:UIImagePickerControllerMediaURL];

 NSString *urlString=[urlvideo path];

NSLog(@"urlString=%@",urlString);

NSString *str = [NSString stringWithFormat:@"you url of server"];

NSURL *url = [NSURL URLWithString:[str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];


ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];

[request setFile:urlString forKey:@"key foruploadingFile"];

[request setRequestMethod:@"POST"];

[request setDelegate:self];

[request startSynchronous];

NSLog(@"responseStatusCode %i",[request responseStatusCode]);

NSLog(@"responseStatusCode %@",[request responseString]);