2014-06-16 24 views
54

因此,此HTML代碼以正確格式爲我提交數據。使用Objective-C POST多部分/表單數據

<form action="https://www.example.com/register.php" method="post" enctype="multipart/form-data"> 
    Name: <input type="text" name="userName"><BR /> 
    Email: <input type="text" name="userEmail"><BR /> 
    Password: <input type="text" name="userPassword"><BR /> 
    Avatar: <input type="file" name="avatar"><BR /> 
    <input type="submit"> 
</form> 

我已經研究過的好一些關於如何做iOS上的multipart/form-data發佈的文章,但沒有真正解釋做什麼,如果有正常的參數以及文件上傳。

你能幫我把代碼發佈在Obj-C嗎?

謝謝!

回答

147

的過程如下:

  1. 創建具有userNameuserEmail,和userPassword參數字典。

    NSDictionary *params = @{@"userName"  : @"rob", 
             @"userEmail" : @"[email protected]", 
             @"userPassword" : @"password"}; 
    
  2. 確定用於圖像的路徑:

    NSString *path = [[NSBundle mainBundle] pathForResource:@"avatar" ofType:@"png"]; 
    
  3. 創建請求:

    NSString *boundary = [self generateBoundaryString]; 
    
    // configure the request 
    
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; 
    [request setHTTPMethod:@"POST"]; 
    
    // set content type 
    
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary]; 
    [request setValue:contentType forHTTPHeaderField: @"Content-Type"]; 
    
    // create body 
    
    NSData *httpBody = [self createBodyWithBoundary:boundary parameters:params paths:@[path] fieldName:fieldName]; 
    
  4. 這是上述用於建立請求的主體的方法,包括:

    - (NSData *)createBodyWithBoundary:(NSString *)boundary 
             parameters:(NSDictionary *)parameters 
              paths:(NSArray *)paths 
             fieldName:(NSString *)fieldName { 
        NSMutableData *httpBody = [NSMutableData data]; 
    
        // add params (all params are strings) 
    
        [parameters enumerateKeysAndObjectsUsingBlock:^(NSString *parameterKey, NSString *parameterValue, BOOL *stop) { 
         [httpBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; 
         [httpBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", parameterKey] dataUsingEncoding:NSUTF8StringEncoding]]; 
         [httpBody appendData:[[NSString stringWithFormat:@"%@\r\n", parameterValue] dataUsingEncoding:NSUTF8StringEncoding]]; 
        }]; 
    
        // add image data 
    
        for (NSString *path in paths) { 
         NSString *filename = [path lastPathComponent]; 
         NSData *data  = [NSData dataWithContentsOfFile:path]; 
         NSString *mimetype = [self mimeTypeForPath:path]; 
    
         [httpBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; 
         [httpBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", fieldName, filename] dataUsingEncoding:NSUTF8StringEncoding]]; 
         [httpBody appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", mimetype] dataUsingEncoding:NSUTF8StringEncoding]]; 
         [httpBody appendData:data]; 
         [httpBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; 
        } 
    
        [httpBody appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; 
    
        return httpBody; 
    } 
    
  5. 上面使用以下實用方法:

    @import MobileCoreServices; // only needed in iOS 
    
    - (NSString *)mimeTypeForPath:(NSString *)path { 
        // get a mime type for an extension using MobileCoreServices.framework 
    
        CFStringRef extension = (__bridge CFStringRef)[path pathExtension]; 
        CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, extension, NULL); 
        assert(UTI != NULL); 
    
        NSString *mimetype = CFBridgingRelease(UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType)); 
        assert(mimetype != NULL); 
    
        CFRelease(UTI); 
    
        return mimetype; 
    } 
    
    - (NSString *)generateBoundaryString { 
        return [NSString stringWithFormat:@"Boundary-%@", [[NSUUID UUID] UUIDString]]; 
    } 
    
  6. 然後提交該請求。這裏有很多很多的選擇。

    例如,如果使用NSURLSession,你可以創建NSURLSessionUploadTask

    NSURLSession *session = [NSURLSession sharedSession]; // use sharedSession or create your own 
    
    NSURLSessionTask *task = [session uploadTaskWithRequest:request fromData:httpBody completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
        if (error) { 
         NSLog(@"error = %@", error); 
         return; 
        } 
    
        NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 
        NSLog(@"result = %@", result); 
    }]; 
    [task resume]; 
    

    或者你可以創建一個NSURLSessionDataTask

    request.HTTPBody = httpBody; 
    
    NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
        if (error) { 
         NSLog(@"error = %@", error); 
         return; 
        } 
    
        NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 
        NSLog(@"result = %@", result); 
    }]; 
    [task resume]; 
    

    以上假設服務器只是返回文本響應。如果服務器返回JSON會更好,在這種情況下,您將使用NSJSONSerialization而不是NSString方法initWithData

    同樣,我使用上面的NSURLSession的完成塊格式,但也可以使用更豐富的基於委託的格式。但這似乎超出了這個問題的範圍,所以我會把它留給你。

但希望這可以說明這個想法。


我是失職,如果我沒有一點的是,除上述容易得多,你可以使用AFNetworking,重複步驟1和2以上,但後來只是打電話:

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; 
manager.responseSerializer = [AFHTTPResponseSerializer serializer]; // only needed if the server is not returning JSON; if web service returns JSON, remove this line 
NSURLSessionTask *task = [manager POST:urlString parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { 
    NSError *error; 
    if (![formData appendPartWithFileURL:[NSURL fileURLWithPath:path] name:@"avatar" fileName:[path lastPathComponent] mimeType:@"image/png" error:&error]) { 
     NSLog(@"error appending part: %@", error); 
    } 
} progress:nil success:^(NSURLSessionTask *task, id responseObject) { 
    NSLog(@"responseObject = %@", responseObject); 
} failure:^(NSURLSessionTask *task, NSError *error) { 
    NSLog(@"error = %@", error); 
}]; 

if (!task) { 
    NSLog(@"Creation of task failed."); 
} 
+1

請注意,您還可以使用NSUUID生成UUID: '的NSString *邊界= [的NSString stringWithFormat:@ 「邊界 - %@」,[NSUUID UUID] UUIDString];' – Olivier

+0

是的,如果你不不需要支持6.0之前的iOS版本,這是一個很好的方法。 – Rob

+2

這是一個夢幻般的答案。榮譽和感謝。 –

1

嘗試將這個用於不同MIME類型的視頻和圖像數據。

NSDictionary *param; 

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 

// 1. Create `AFHTTPRequestSerializer` which will create your request. 
AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer]; 
NSMutableURLRequest *request; 

NSData *fileData; 
if ([objDoc.url containsString:@".mp4"]) { 
    manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:@"application/json"]; 
    [serializer setValue:@"video/mp4" forHTTPHeaderField:@"Content-Type"]; 
    manager.requestSerializer = serializer; 
} 

// 2. Create an `NSMutableURLRequest`. 

NSLog(@"filename =%@",objDoc.url); 
request= [serializer multipartFormRequestWithMethod:@"POST" URLString:strUrl parameters:param constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { 

    if ([objDoc.url containsString:@".mp4"]) { 
     [formData appendPartWithFileData:fileData 
            name:@"File" 
           fileName:@"video.mp4" 
           mimeType:@"video/mp4"]; 

    }else{ 
     [formData appendPartWithFileData:fileData 
            name:@"File" 
           fileName:@"image.jpeg" 
           mimeType:@"image/jpeg"]; 
    } 

} error:nil]; 

// 3. Create and use `AFHTTPRequestOperationManager` to create an `AFHTTPRequestOperation` from the `NSMutableURLRequest` that we just created. 

self.objeDocument.isUploading = [NSNumber numberWithInt:1]; 

self.operation = [manager HTTPRequestOperationWithRequest:request 
                success:^(AFHTTPRequestOperation *operation, id responseObject) { 

                 NSLog(@"Success %@", responseObject); 
                } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
                 UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Error!" message:@"The document attached has failed to upload." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; 
                 [alert show]; 
                 [self.operation cancel]; 
                 NSLog(@"Failure %@", error.description); 
                }]; 


// 4. Set the progress block of the operation. 
[self.operation setUploadProgressBlock:^(NSUInteger __unused bytesWritten, 
             long long totalBytesWritten, 
             long long totalBytesExpectedToWrite) { 
    NSLog(@"Wrote %lld/%lld", totalBytesWritten, totalBytesExpectedToWrite); 
    float progress = (float)totalBytesWritten/(float)totalBytesExpectedToWrite; 


}]; 

// 5. Begin! 
[self.operation start]; 
1

POST使用多或表單數據和Objective-C的

-(void)multipleimageandstring 
{ 
    NSString *[email protected]"URL NAME"; 

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init] ; 
    [request setURL:[NSURL URLWithString:urlString]]; 
    [request setHTTPMethod:@"POST"]; 

    NSMutableData *body = [NSMutableData data]; 

    NSString *boundary = @"---------------------------14737809831466499882746641449"; 
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary]; 
    [request addValue:contentType forHTTPHeaderField:@"Content-Type"]; 

    // file 
    float low_bound = 0; 
    float high_bound =5000; 
    float rndValue = (((float)arc4random()/0x100000000)*(high_bound-low_bound)+low_bound);//image1 
    int intRndValue = (int)(rndValue + 0.5); 
    NSString *str_image1 = [@(intRndValue) stringValue]; 

    UIImage *chosenImage1=[UIImage imageNamed:@"Purchase_GUI_curves-12 copy.png"]; 

    NSData *imageData = UIImageJPEGRepresentation(chosenImage1, 90); 
    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; 
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"files\"; filename=\"%@.png\"\r\n",str_image1] dataUsingEncoding:NSUTF8StringEncoding]]; 
    [body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; 
    [body appendData:[NSData dataWithData:imageData]]; 
    [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; 





    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; 
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"name\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; 
    [body appendData:[@"Nilesh" dataUsingEncoding:NSUTF8StringEncoding]]; 
    [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; 

    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; 
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"apipassword\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; 
    [body appendData:[[NSString stringWithString:app.password] dataUsingEncoding:NSUTF8StringEncoding]]; 
    [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; 

    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; 
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"adminId\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; 
    [body appendData:[[NSString stringWithString:app.adminId] dataUsingEncoding:NSUTF8StringEncoding]]; 
    [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; 

    // close form 
    [body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]]; 
    // set request body 
    [request setHTTPBody:body]; 

    //return and test 
    NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; 
    NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding]; 

    NSLog(@"%@", returnString); 

} 
0

我這個掙扎了一會兒多張圖片,如果你正在尋找上傳多張圖片或任何其他類型的文件,可以做到使用AFNetworking 3.0

NSDictionary *params = @{key  : value, 
          ..... etc 
         }; 

NSString *urlString = @"http://..... your endpoint url"; 

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; 
manager.responseSerializer = [AFHTTPResponseSerializer serializer]; // only needed if the server is not returning JSON; 

NSURLSessionTask *task = [manager POST:urlString parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { 
    for (int x = 0 ; x< contentArray.count; x++) { 
     AttachmentsModel *model = contentArray[x]; 

     if(model.type == ImageAttachmentType){ 
      [formData appendPartWithFileData:model.data name:model.name fileName:model.fileName mimeType:model.mimeType]; 

     }else if(model.type == AudioAttachmentType){ 
      NSURL *urlVideoFile = [NSURL fileURLWithPath:model.path]; 
      [formData appendPartWithFileURL:urlVideoFile name:model.name fileName:model.fileName mimeType:model.mimeType error:nil]; 
     }else{ 
      [formData appendPartWithFileURL:model.url name:model.name fileName:model.fileName mimeType:model.mimeType error:nil]; 

     } 

    } 
} progress:nil success:^(NSURLSessionTask *task, id responseObject) { 
    [Utility stopLoading]; 

    NSString *result = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; 
    NSLog(@"result = %@", result); 

    id json = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:nil]; 


    if (block) { 

     //your response comes here 
    } 

} failure:^(NSURLSessionTask *task, NSError *error) { 
    NSLog(@"error = %@", error); 

}]; 

if (!task) { 
    NSLog(@"Creation of task failed."); 
} 

以下內容,這裏是我的AttachmentsModel看起來像:

// AttachmentsModel.h 

typedef enum AttachmnetType{ 
    ImageAttachmentType, 
    AudioAttachmentType, 
    VideoAttachmentType 
} AttachmnetType; 

@interface AttachmentsModel : NSObject 

@property (strong, nonatomic) NSString *path; 
@property (strong, nonatomic) NSData *data; 
@property (strong, nonatomic) NSString *mimeType; 
@property (strong, nonatomic) NSString *name; 
@property (strong, nonatomic) NSString *fileName; 
@property (strong, nonatomic) NSURL *url; 
相關問題