【问题标题】:Upload video from library Afnetworking multipart从库 Afnetworking 多部分上传视频
【发布时间】:2025-12-16 11:10:01
【问题描述】:

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

当我从画廊中选择电影时,有这些信息:

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

【问题讨论】:

    标签: ios iphone video file-upload afnetworking


    【解决方案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,以便我们更好地帮助您 - 包括您预期的详细信息以及它与实际发生的情况有何不同.

    【讨论】:

      【解决方案2】:

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

      【讨论】: