从库Afnetworking multipart上传视频

时间:2014-02-04 09:26:51

标签: ios iphone video file-upload afnetworking

我必须从图库上传视频并将其发送到服务器多部分。

当我从图库中选择电影时,请提供以下信息:

 self.videoDictionary = {
    UIImagePickerControllerMediaType = "public.movie";
    UIImagePickerControllerMediaURL = "file:///Users/alin/Library/Application%20Support/iPhone%20Simulator/7.0.3/Applications/714D0B71-80EA-4B6C-9ACF-A287C8F40121/tmp/trim.FF287468-B25E-4EEA-8EAB-A485842476FA.MOV";
    UIImagePickerControllerReferenceURL = "assets-library://asset/asset.MOV?id=393E740F-B7F4-46DA-BB09-69AB92C34660&ext=MOV";
} 

我的WS签名如下:

参数:

  • 散列
  • 标题
  • 描述
  • 视频

    我尝试上传视频时遇到问题:

    -(void)addVideoRequestToWS
    {
    BusinessLogic *bl = [BusinessLogic sharedManager];
    
    ApiClientBlitzApp *client = [ApiClientBlitzApp sharedClient];
    
    NSString *videoURL = [self.videoDictionary objectForKey:@"UIImagePickerControllerReferenceURL"];
    NSData *videoData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath: videoURL]]; // I suppose my problem are from two lines of code
    
    NSMutableURLRequest *request = [client multipartFormRequestWithMethod:@"POST" path:getAddVideo parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
    
           [formData appendPartWithFormData:[[NSString stringWithFormat:@"%@",bl.currentUser.hash] dataUsingEncoding:NSUTF8StringEncoding] name:@"hash"];
           [formData appendPartWithFormData:[[NSString stringWithFormat:@"%@",self.textFieldTitle.text] dataUsingEncoding:NSUTF8StringEncoding] name:@"title"];
           [formData appendPartWithFormData:[[NSString stringWithFormat:@"%@",self.textFieldDescription.text]] dataUsingEncoding:NSUTF8StringEncoding] name:@"description"];
           [formData appendPartWithFileData:videoData name:@"video_file" fileName:@"testvideo.mov" mimeType:@"video/quicktime"];
      }];
    
    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    [operation setUploadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
         NSLog(@"Sent %lld of %lld bytes", totalBytesWritten, totalBytesExpectedToWrite);
    
    }];
    [client enqueueHTTPRequestOperation:operation];
    
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    
        NSData *JSONData = [operation.responseString dataUsingEncoding:NSUTF8StringEncoding];
        NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:JSONData options:NSJSONReadingMutableContainers error:nil];
    
        NSLog(@"jsonObject of the list = %@", jsonObject);
    }
     failure:^(AFHTTPRequestOperation *operation, NSError *error) {
         NSLog(@"error: %@", operation.responseString);
         NSLog(@"%@",error);
     }];
    [operation start];
    }
    

2 个答案:

答案 0 :(得分:1)

你有一些问题,并没有提到你遇到的问题。

首先,这一行:

[client enqueueHTTPRequestOperation:operation];

可能会立即开始操作,在设置完成块之前,您不应该这样做。

第二,这一行:

[operation start];

立即开始操作(如果已经添加的NSOperationQueue尚未启动)。您应该只执行其中一个,而不是两个,并且应该在配置您的操作后应该完成的任何操作。

最后,对于您的多部分上传:

NSMutableURLRequest *request = [client multipartFormRequestWithMethod:@"POST" path:getAddVideo parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {

       [formData appendPartWithFormData:[[NSString stringWithFormat:@"%@",bl.currentUser.hash] dataUsingEncoding:NSUTF8StringEncoding] name:@"hash"];
       [formData appendPartWithFormData:[[NSString stringWithFormat:@"%@",self.textFieldTitle.text] dataUsingEncoding:NSUTF8StringEncoding] name:@"title"];
       [formData appendPartWithFormData:[[NSString stringWithFormat:@"%@",self.textFieldDescription.text]] dataUsingEncoding:NSUTF8StringEncoding] name:@"description"];
       [formData appendPartWithFileData:videoData name:@"video_file" fileName:@"testvideo.mov" mimeType:@"video/quicktime"];
  }];

除非你的服务器做了一些疯狂的事情,否则这可能是错误的。首先,您不需要使用字符串格式化程序来传递像self.textFieldTitle.text这样的字符串。第二,什么是hash?通常,散列是NSUInteger,这种方式不能与字符串格式化器一起使用。无论如何,都不可能肯定地说,因为你没有提供关于正在发生的事情以及你想要发生什么的足够细节。

您应该设置一个HTTP代理,例如Charles,以便检查您的应用实际传输的流量。或者,至少应该安装AFHTTPRequestOperationLogger,它会将大部分内容记录到Xcode控制台。将您发送的内容与服务器的预期进行比较。在成功和失败块内设置断点,并在看到错误时检查错误。如果再次卡住,请在Stack Overflow上发布控制台的输出,以便我们更好地帮助您 - 包括您期望的详细信息以及它与实际发生的内容的区别

答案 1 :(得分:0)

SWIFT 版本:使用AFNetworking上传视频。它还跟踪进展情况。

    func createVideoPost(completion:(success: Bool) -> Void) {

    progressView = NSBundle.mainBundle().loadNibNamed("UploadProgressView", owner: nil, options: nil).first! as? UploadProgressView

    progressView?.frame = CGRectMake(0,
        0,
        self.parentController!.view.frame.size.width,
        self.parentController!.view.frame.size.height)

    self.parentController!.view.addSubview(progressView!)
    self.parentController!.navigationItem.hidesBackButton = true
    progressView?.cancelBtn.addTarget(self, action: "cancelUploading:", forControlEvents: .TouchUpInside)

    // Add video url to the param if its already on server
    if self.videoPath!.hasPrefix("http:") || self.videoPath!.hasPrefix("https:") {
      parameter?.setObject(self.videoPath!, forKey: "video_file")
    }

    let requestSerializer = AFHTTPRequestSerializer()
    var request: NSMutableURLRequest?
    var error: NSError?

    do {
        request = try  requestSerializer.multipartFormRequestWithMethod("POST", URLString: WebConstants.BaseURL, parameters: parameter! as [NSObject : AnyObject], constructingBodyWithBlock: { (formData: AFMultipartFormData!) -> Void in

            //var videoData: NSData?
            if self.videoPath!.hasPrefix("http:") || self.videoPath!.hasPrefix("https:") {
                //videoData = NSData(contentsOfURL: NSURL(string: self.videoPath!)!)
                //formData.appendPartWithFileData(videoData!, name: "files[]", fileName: "movie.mp4", mimeType: "video/mp4")
            } else {
                //videoData = NSData(contentsOfURL: NSURL(fileURLWithPath: self.videoPath!))
                do {
                    try formData.appendPartWithFileURL(NSURL(fileURLWithPath: self.videoPath!), name: "files[]", fileName: "movie.mp4", mimeType: "video/mp4")

                } catch {
                    print("Error in uploading")
                }
            }


        })

    } catch {
        //...
    }


    let manager: AFURLSessionManager = AFURLSessionManager(sessionConfiguration: NSURLSessionConfiguration.defaultSessionConfiguration())
    manager.responseSerializer = AFJSONResponseSerializer(readingOptions: NSJSONReadingOptions.AllowFragments)

    var progress: NSProgress?
    uploadTask = manager.uploadTaskWithStreamedRequest(request,
        progress: &progress, completionHandler: { (response: NSURLResponse?, responseObject: AnyObject?, error: NSError?) -> Void in

            if (error != nil) {
                //print(error?.description)
                self.parentController!.navigationItem.hidesBackButton = false
                self.progressView?.removeFromSuperview()
                completion(success: false)

            } else {

                // remove the video from my directory as its uploading is completed successfully
                do {
                    try NSFileManager.defaultManager().removeItemAtURL(NSURL(fileURLWithPath: self.videoPath!))
                    print("memory cleaned, temp videos deleted")
                } catch {
                    print("memory not cleared for temp videos")
                }

                Utility.clearAllTempFiles()
                self.parentController!.navigationItem.hidesBackButton = false
                self.progressView?.removeFromSuperview()
                NSNotificationCenter.defaultCenter().postNotificationName(Constants.LaunchDidCreatedNotificationKey, object: nil)
                completion(success: true)

            }
    })

    uploadTask!.resume()
    progress?.addObserver(self, forKeyPath: "fractionCompleted", options: NSKeyValueObservingOptions.Initial, context: nil)


}

func cancelUploading(sender: UIButton) {
    uploadTask!.cancel()
    progressView?.removeFromSuperview()
}

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {

    let progress: NSProgress = object as! NSProgress
    dispatch_async(dispatch_get_main_queue(), {
        //print(progress.fractionCompleted)
        self.progressView!.progressBar!.setProgress(Float(progress.fractionCompleted), animated: true)
    })

}