Example of multipart/form-data post in Objective C
Use Objective C to implement the http post method and send data with Content-Type in multipart/form-data format. Support file and picture upload.
To get the mime type of the file under the IOS project, you need to add the MobileCoreServices.framework
in the Xcode. Build Phases -> Link Binary With Libraries
, add MobileCoreServices.framework
. Refer to Get a file mime type in Objective C.
Example
HttpPostMultipart.h
#import <Foundation/Foundation.h>
@interface HttpPostMultipart:NSObject
-(id)initWithUrl:(NSString *)urlString;
@property(nonatomic) NSMutableURLRequest *request;
@property(nonatomic) NSString *urlString;
@property(nonatomic) NSMutableDictionary *headers;
@property(nonatomic) NSMutableDictionary *fields;
@property(nonatomic) NSMutableDictionary *files;
/// Adds a header to the request
/// @param key Header key
/// @param value Header value
-(void)addHeader:(NSString *)key value:(NSString *)value;
/// Adds a form field to the request
/// @param key Field name
/// @param value Field value
-(void)addFormField:(NSString *)key value:(NSString *)value;
/// Adds a upload file section to the request
/// @param key Field name of the upload file
/// @param path File path
-(void)addFormFile:(NSString *)key path:(NSString *)path;
/// Completes the request
/// @param callback The callback block
- (void)finish:(void(^)(NSData *, NSURLResponse *, NSError *))callback;
@end
HttpPostMultipart.m
#import "HttpPostMultipart.h"
#import <MobileCoreServices/MobileCoreServices.h>
@implementation HttpPostMultipart
-(id)initWithUrl:(NSString *)urlString{
self.request = [[NSMutableURLRequest alloc]init];
self.urlString = urlString;
self.headers = [[NSMutableDictionary alloc]init];
self.fields = [[NSMutableDictionary alloc]init];
self.files = [[NSMutableDictionary alloc]init];
return self;
}
-(void)addHeader:(NSString *)key value:(NSString *)value{
[self.headers setObject:value forKey:key];
}
-(void)addFormField:(NSString *)key value:(NSString *)value{
[self.fields setObject:value forKey:key];
}
-(void)addFormFile:(NSString *)key path:(NSString *)path{
[self.files setObject:path forKey:key];
}
- (void)finish:(void (^)(NSData *, NSURLResponse *, NSError *))callback{
NSURL *url = [[NSURL alloc]initWithString:self.urlString];
[self.request setURL:url];
[self.request setHTTPMethod:@"POST"];
// Add haders
for (NSString *key in self.headers){
NSString *value = self.headers[key];
[self.request setValue:value forHTTPHeaderField:key];
}
// Add Content-Type
NSString *boundary = @"unique-consistent-string";
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[self.request setValue:contentType forHTTPHeaderField:@"Content-Type"];
// Add fields
NSMutableData *body = [NSMutableData data];
for (NSString *key in self.fields){
NSString *value = self.fields[key];
// add params (all params are strings)
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=%@\r\n\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"%@\r\n", value] dataUsingEncoding:NSUTF8StringEncoding]];
}
// Add file
for (NSString *key in self.files){
NSString *path = self.files[key];
NSString *fileName = [path lastPathComponent];
NSString *fileExtension = [path pathExtension];
NSString *contentType = [self getMimeType:fileExtension];
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=%@; filename=%@\r\n", key, fileName] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", contentType] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[NSData dataWithContentsOfFile:path]];
[body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
}
if ([body length] > 0) {
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
// setting the body of the post to the reqeust
[self.request setHTTPBody:body];
// set the content-length
NSString *postLength = [NSString stringWithFormat:@"%ld", [body length]];
[self.request setValue:postLength forHTTPHeaderField:@"Content-Length"];
}
void (^completionHandler)(NSData *, NSURLResponse *, NSError *) = ^(NSData *data, NSURLResponse *response, NSError *error) {
if (callback) {
callback(data, response, error);
}
};
[[[NSURLSession sharedSession] dataTaskWithRequest:self.request completionHandler:completionHandler] resume];
}
/// Get mime type of the file
/// @param fileExtension file extension
- (NSString *)getMimeType:(NSString *)fileExtension{
NSString *UTI = (__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)fileExtension, NULL);
NSString *mimeType = (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)UTI, kUTTagClassMIMEType);
return mimeType;
}
@end
Use it
NSString *url = @"http://localhost";
HttpPostMultipart *request = [[HttpPostMultipart alloc]initWithUrl:url];
// Add user-agent
[request addHeader:@"User-Agent" value:@"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36"];
// Add field
[request addFormField:@"username" value:@"test"];
// Add a image
[request addFormFile:@"pictures" path:@"/Users/apple/Downloads/201228bli.bmp"];
void (^completionHandler)(NSData *, NSURLResponse *, NSError *) = ^(NSData *data, NSURLResponse *response, NSError *error) {
if (data == nil || data.length == 0 || response == nil || [(NSHTTPURLResponse *)response statusCode] != 200) {
NSLog(@"error");
return;
}
NSLog(@"success: %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
};
[request finish:completionHandler];