10

Tôi đang cố gắng tải lên tệp video/hình ảnh bằng phương pháp - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL; bằng cách sử dụng dữ liệu biểu mẫu nhiều phần. Nhưng bằng cách nào đó tôi không thể tải lên tập tin và tôi nhận được lỗi "stream ended unexpectedly".không thể tải tệp lên bằng cách sử dụng dữ liệu biểu mẫu nhiều phần NSURLSession trong iOS

Yêu cầu

  1. Tải lên video/tập tin ảnh đến máy chủ
  2. App nên hỗ trợ tải nền (Tiếp tục quá trình tải lên ngay cả sau khi ứng dụng đi vào nền)
  3. server hy vọng dữ liệu được được gửi bằng dữ liệu biểu mẫu nhiều phần.

Methods/API sử dụng để đạt được điều này

  1. NSURLSession phiên nền API (Hoàn thành mã được liệt kê dưới đây)

    2. - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL

thách thức/Những vấn đề đang đối mặt với

  1. phải đối mặt với lỗi "stream ended unexpectedly" mỗi khi tôi đang sử dụng API này cho quá trình upload

điểm cần lưu ý

  1. Việc tải ngày càng thành công với các mã tương tự nếu tôi đang sử dụng NSURLConnection thay vì NSURLSession.

  2. NSURLSession quá trình tải lên nền dự kiến ​​vị trí tệp (NSURL) làm thông số, không chấp nhận NSData. Nó không cho phép chúng tôi chuyển đổi tệp thành NSData trước khi tải lên, nghĩa là chúng tôi không thể thêm NSData vào nội dung tệp.

Cần giúp đỡ về điểm sau đây

  1. Có bất kỳ sai lầm trong cơ thể formdata nhiều phần dữ liệu đang được hình thành (lưu ý - Cùng mã đang làm việc với NSURLConnection)

  2. Tôi đang đi sai trong cách tiếp cận của tôi?

  3. Chúng tôi có cần thực hiện bất kỳ thay đổi nào ở cấp máy chủ để hỗ trợ tải lên NSURLSession backgroundSession không? (trong phân tích dữ liệu hay cái gì khác?)

    Đây là mã đang được sử dụng để tải lên một tập tin

NSString * BoundaryConstant = @ "---------- V2ymHFg03ehbqgZCaKO6jy";

// string constant for the post parameter 'file'. My server uses this name: `file`. Your's may differ 
    NSString* FileParamConstant = @"file"; 

    // the server url to which the image (or video) is uploaded. Use your server url here 

    url=[NSURL URLWithString:[NSString stringWithFormat:@"%@%@%d",baseURL,@"posts/post/update/",createPostObject.PostID]];  


    // create request 
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; 
    [request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData]; 
    [request setHTTPShouldHandleCookies:NO]; 
    [request setTimeoutInterval:120]; 
    [request setHTTPMethod:@"POST"]; 
    [request addValue:@"multipart/form-data" forHTTPHeaderField:@"Content-Type"]; 

    [request setURL:url]; 

    // set Content-Type in HTTP header 
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", BoundaryConstant]; 
    [request setValue:contentType forHTTPHeaderField: @"Content-Type"]; 

    if([[NSUserDefaults standardUserDefaults] objectForKey:@"accessToken"]){ 

     [request setValue:[[NSUserDefaults standardUserDefaults] objectForKey:@"accessToken"] forHTTPHeaderField:AccessTokenKey]; 

    } 

    // post body 
    NSMutableData *body = [NSMutableData data]; 

    // add params (all params are strings) 
    for (NSString *param in self.postParams) { 

     NSLog(@"param is %@",param); 

     [body appendData:[[NSString stringWithFormat:@"--%@\r\n", BoundaryConstant] dataUsingEncoding:NSUTF8StringEncoding]]; 
     [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", param]    dataUsingEncoding:NSUTF8StringEncoding]]; 
     [body appendData:[[NSString stringWithFormat:@"%@\r\n", [self.postParams objectForKey:param]] dataUsingEncoding:NSUTF8StringEncoding]]; 
    } 

    // add video file name to body 

     [body appendData:[[NSString stringWithFormat:@"--%@\r\n", BoundaryConstant] dataUsingEncoding:NSUTF8StringEncoding]]; 
     [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"file.mp4\"\r\n", FileParamConstant] dataUsingEncoding:NSUTF8StringEncoding]]; 
     [body appendData:[[NSString stringWithString:@"Content-Type: video/mp4\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; 
     // [body appendData:self.dataToPost]; 
     [body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; 

     [body appendData:[[NSString stringWithFormat:@"--%@--\r\n", BoundaryConstant] dataUsingEncoding:NSUTF8StringEncoding]]; 



    // setting the body of the post to the request 
    [request setHTTPBody:body]; 

    // set the content-length 
    NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[body length]]; 
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"]; 

    NSLog(@"Request body %@", [[NSString alloc] initWithData:[request HTTPBody] encoding:NSUTF8StringEncoding]); 

    NSURLSessionConfiguration * backgroundConfig = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"backgroundtask1"]; 

    NSURLSession *backgroundSeesion = [NSURLSession sessionWithConfiguration: backgroundConfig delegate:self delegateQueue: [NSOperationQueue mainQueue]]; 


    NSURLSessionUploadTask *uploadTask = [backgroundSeesion uploadTaskWithRequest:request fromFile:self.videoUrl]; 
    [uploadTask resume]; 
+0

Bạn dường như để thiết lập "trang nội dung Nhập "hai lần. Bạn không chắc chắn cách thức hoạt động. Không chắc chắn về phần còn lại. Tôi làm một cái gì đó tương tự, nhưng tạo ra bộ đệm tải lên riêng biệt (trong một hàm C++) và chỉ cần thêm bộ đệm lỗ. Vì vậy, tôi không phải đóng góp nhiều hơn nữa. –

Trả lời

9

Bạn hiện không tải lên những gì bạn nghĩ. Mục đích của bạn là để dữ liệu nội dung được tải lên như hiện tại. Thay vào đó, khi bạn gọi uploadTaskWithRequest:fromFile:, phương thức đó sẽ thực hiện hiệu quả mọi giá trị HTTPBody hoặc HTTPBodyStream trong yêu cầu và thay thế chúng bằng nội dung của URL mà bạn đã chuyển qua thông số fromFile:. Vì vậy, trừ khi bạn đang viết khối dữ liệu nội dung được mã hóa biểu mẫu đó vào URL của tệp đó ở một nơi khác, bạn đang tự tải tệp lên thay vì dữ liệu biểu mẫu nhiều phần.

Bạn cần phải chỉnh sửa mã của mình để ghi dữ liệu biểu mẫu vào tệp thay vì lưu trữ dữ liệu trong HTTPBody, sau đó chuyển URL của tệp đó đến thông số fromFile:.

+0

xin vui lòng bạn có thể cung cấp một đoạn mã, cảm ơn bạn. –

+0

1. Thay đổi fromFile: thành fromData :, và chuyển giá trị của 'body'. – dgatwood

+0

2. Uncomment // [body appendData: self.dataToPost]; và thay đổi self.dataToPost thành [NSData dataWithContentsOfURL: self.videoURL]. – dgatwood

4

Để tránh lãng phí thời gian đối phó với nó.

hoàn chỉnh đoạn dựa trên câu trả lời @dgatwood

private func http(request: URLRequest){ 
     let configuration = URLSessionConfiguration.default 
     let session = URLSession(configuration: configuration, delegate: self, delegateQueue: .main) 
     /*Tweaking*/ 
     let task = session.uploadTask(with: request, from: request.httpBody!) 
     task.resume() 
    } 

Và .. đừng quên để thêm Headers theo yêu cầu đối tượng như

request.setValue("multipart/form-data; boundary=\(yourboundary)", forHTTPHeaderField: "Content-Type") 
Các vấn đề liên quan