Tyrone Prude
Tyrone Prude

Reputation: 382

Upload video from library Afnetworking multipart

I have to upload a video from gallery and send it to server multipart.

When I select the movie from gallery a have those information :

 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";
} 

My WS signature look like this :

Params :

Upvotes: 0

Views: 3808

Answers (2)

Abdul Yasin
Abdul Yasin

Reputation: 3508

SWIFT version: Uploading video using AFNetworking. It also tracks progress.

    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)
    })

}

Upvotes: 0

Aaron Brager
Aaron Brager

Reputation: 66242

You have a few problems, and haven't mentioned which you're encountering.

First, this line:

[client enqueueHTTPRequestOperation:operation];

may immediately start the operation, which you should never do before you set your completion blocks.

Second, this line:

[operation start];

immediately starts the operation (if the NSOperationQueue you already added it to hasn't started already). You should only do one or the other of these, not both, and whichever you should do should be done after you configure your operation.

Finally, for your multi-part upload:

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"];
  }];

Unless your server is doing some crazy stuff, this might be wrong. First of all, you don't need to use the string formatter to pass in a string like self.textFieldTitle.text. Second of all, what is hash? Typically a hash is an NSUInteger, which won't work with the string formatter this way. No matter what, it's impossible to say for sure because you haven't provided enough detail about what is happening and what you want to happen.

You should set up an HTTP proxy like Charles in order to inspect the traffic your app is actually transmitting. Or, at least, you should install AFHTTPRequestOperationLogger, which will log most stuff to your Xcode console. Compare what you're sending to what your server is expecting. Set breakpoints inside the success and failure blocks and inspect the error when you see it. And if you get stuck again, post the output of your console on Stack Overflow so we can help you better - include details about what you expect and how it differs from what's actually happening.

Upvotes: 1

Related Questions