10

マルチパートフォームデータを使用して- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL; メソッドを使用してビデオ/画像ファイルをアップロードしようとしています。しかし、何とか私はファイルをアップロードすることができませんし、私は "stream ended unexpectedly"エラーを取得しています。iOSでNSURLSessionのマルチパートフォームデータを使用してファイルをアップロードできません

  1. (アプリがバックグラウンドに移行した後も、アップロード処理を続行します)アプリケーションがバックグラウンドのアップロードをサポートする必要があり
  2. サーバに動画/画像ファイルをアップロードServerは、データがあることを想定してい

    要件複数パートのフォームデータを使用して送信されます。

方法/この

  1. NSURLSession背景セッションAPI(以下に記載の完全なコード)

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

課題/問題点を達成するために使用されるAPIの直面しているstream ended unexpectedly」エラーに私がアップロードが同じコードで成功してきている

  1. を注意すべきでアップロードプロセスのために

ポイントを、このAPIを使用していますたびに直面

  1. 私がNSURLSessionの代わりにNSURLConnectionを使用している場合。

  2. NSURLSessionバックグラウンドアップロードプロセスでは、パラメータとしてファイルの場所(NSURL)が必要ですが、NSDataは受け入れません。アップロード前にファイルをNSDataに変換することはできません。つまり、ファイルボディにNSDataを追加することはできません。 ( - 同じコードがNSURLConnectionで作業しているノート)

は、以下の点

  1. 形成されているマルチパートFORMDATA体内のいずれかのミスがありに助けが必要私のアプローチでどこが間違っていますか?

  2. NSURLSession backgroundSessionのアップロードをサポートするためにサーバーレベルで変更する必要がありますか? (データの解析や他の何か?)

    ここ

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

よう要求オブジェクトにヘッダを追加することを忘れないでくださいあなたは「のContentを設定しているように見えますタイプ "を2回入力します。それがどのように機能するかわからない。残りの部分についてはわかりません。私は似たようなことをしますが、アップロードバッファを別々に(C++の関数で)作り、ホールバッファを追加するだけです。だから私はこれ以上貢献する必要はありません。 –

答えて

9

あなたは自分の考えをアップロードしていません。あなたの意図は、身体データをそのままアップロードすることです。その代わりに、uploadTaskWithRequest:fromFile:を呼び出すと、そのメソッドは実質的に要求の中のいずれかのHTTPBodyまたはHTTPBodyStream値を取り除き、fromFile:パラメータを使って渡したURLの内容で置き換えます。

フォームエンコードされたボディデータのブロックをそのファイルURLに書き込まない限り、マルチパートフォームデータの代わりにファイルを単独でアップロードしています。

HTTPBodyに保存する代わりに、フォームデータをファイルに書き込むためにコードを調整してから、そのファイルのURLをfromFile:パラメータに渡す必要があります。

+0

コードスニペットを入力してください。ありがとうございます。 –

+0

1. fromFile:fromData:に変更し、 'body'の値を渡します。 – dgatwood

+0

2. // [body appendData:self.dataToPost]のコメントを外します。 self.dataToPostを[NSData dataWithContentsOfURL:self.videoURL]に変更します。 – dgatwood

4

時間を無駄にしないようにする。 @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() 
    } 

そして...

request.setValue("multipart/form-data; boundary=\(yourboundary)", forHTTPHeaderField: "Content-Type") 
関連する問題