10
hochladen

Ich versuche, eine Video/Image-Datei mit - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL; Methode mit mehrteiligen Formulardaten hochladen. Aber irgendwie bin ich nicht in der Lage, die Datei hochzuladen, und ich bekomme "stream ended unexpectedly" Fehler.Datei kann nicht mit NSURLSession mehrteilige Formulardaten in iOS

Anforderungen

  1. ein Video-/Bilddatei auf den Server hochladen
  2. App Hintergrund Uploads unterstützen sollte (weiter den Upload-Prozess auch nach der App in den Hintergrund geht)
  3. Server die Daten erwartet werden gesendet mit mehrteiligen Formulardaten.

Methoden/API dieses

  1. NSURLSession Hintergrund Sitzung API (Complete Code unten aufgeführt)

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

Herausforderungen/Probleme zu erreichen, verwendet konfrontiert sein

  1. "stream ended unexpectedly" Fehler jedes Mal, wenn ich diese API mit Blick für den Upload-Prozess mit dem gleichen Code

    1. Der Upload wird immer erfolgreich bin mit

    Punkte zu beachten, Wenn ich NSURLConnection statt NSURLSession benutze.

  2. NSURLSession Hintergrund Upload-Prozess erwartet den Speicherort der Datei (NSURL) als Parameter, akzeptiert NSData nicht. Es erlaubt uns nicht, die Datei vor dem Hochladen in NSData zu konvertieren, d. H., Wir können NSData nicht zum Dateikörper hinzufügen.

Brauchen auf folgende Punkte helfen

  1. Gibt es einen Fehler in der Multipart-Formulardaten Körper, der gebildet wird (Anmerkung - Der gleiche Code arbeitet mit NSURLConnection)

  2. Wo gehe ich falsch herum?

  3. Müssen wir Änderungen auf Serverebene vornehmen, um NSURLSession backgroundSession Uploads zu unterstützen? (in Datenanalyse oder etwas anderes?)

    Hier ist der Code, der für das Hochladen einer Datei

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

// 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

Sie scheinen hinzufügen, um „Content- Tippe zweimal. Nicht sicher, wie das geht. Ich bin mir nicht sicher über den Rest. Ich mache etwas ähnliches, aber erstelle den Upload-Puffer separat (in einer C++ Funktion) und füge einfach den Lochpuffer hinzu. Also muss ich nicht viel mehr beitragen. –

Antwort

9

Sie laden nicht hoch, was Sie denken, dass Sie sind. Ihre Absicht ist, dass die Körperdaten so wie sie sind hochgeladen werden. Wenn Sie uploadTaskWithRequest:fromFile: aufrufen, gibt diese Methode stattdessen oder Werte in der Anforderung effektiv aus und ersetzt sie durch den Inhalt der URL, die Sie über den Parameter fromFile: übergaben.

Wenn Sie also diesen Block aus formcodierten Bodydaten nicht an die Datei-URL irgendwo anders schreiben, laden Sie die Datei selbst hoch, anstatt die mehrteiligen Formulardaten.

Sie müssen Ihren Code optimieren, um die Formulardaten in eine Datei zu schreiben, statt sie in HTTPBody zu speichern, und dann die URL dieser Datei an den Parameter fromFile: zu übergeben.

+0

Bitte geben Sie ein Code-Snippet, danke. –

+0

1. Ändern Sie vonFile: in fromData: und übergeben Sie den Wert von 'body'. – dgatwood

+0

2. Unkommentieren // [body appendData: self.dataToPost]; und ändern Sie self.dataToPost zu [NSData dataWithContentsOfURL: self.videoURL]. – dgatwood

4

Um zu vermeiden, Zeit damit zu verschwenden.

Der komplette Schnipsel basierend auf @dgatwood Antwort

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

Und .. vergessen Sie nicht die Header auf Anfrage Objekt wie

request.setValue("multipart/form-data; boundary=\(yourboundary)", forHTTPHeaderField: "Content-Type") 
Verwandte Themen