Upload Data using Multipart

Mohd Danish Khan
3 min readApr 21, 2017

--

<form action=”/action_page_binary.asp” method=”post” enctype=”multipart/form-data”>
First name: <input type=”text” name=”fname”><br>
Last name: <input type=”text” name=”lname”><br>
<input type=”submit” value=”Submit”>
</form>

What is Multipart or Multipart/form-data?

The enctype attribute specifies how the form-data should be encoded when submitting it to the server. Multipart/form-data is one of the most used enctype/content type.
In multipart, each of the field to be sent has its content type, file name and data separated by boundary from other field.

No encoding of the data is necessary, because of the unique boundary. The binary data is sent as it is. The server reads the until the next boundary string.

Definition of Multipart/Form data:

The media-type multipart/form-data follows the rules of all multipart MIME data streams as outlined in [RFC 2046]. In forms, there are a series of fields to be supplied by the user who fills out the form. Each field has a name. Within a given form, the names are unique.

“multipart/form-data” contains a series of parts. Each part is expected to contain a content-disposition header [RFC 2183] where the disposition type is “form-data”, and where the disposition contains an (additional) parameter of “name”, where the value of that parameter is the original field name in the form. For example, a part might contain a header:

Content-Disposition: form-data; name=”user”
with the value corresponding to the entry of the “user” field.

Field names originally in non-ASCII character sets may be encoded within the value of the “name” parameter using the standard method described in RFC 2047. As with all multipart MIME types, each part has an optional “Content-Type”, which defaults to text/plain.

If the contents of a file are returned via filling out a form, then the file input is identified as the appropriate media type, if known, or “application/octet-stream”.

If multiple files are to be returned as the result of a single form entry, they should be represented as a “multipart/mixed” part embedded within the “multipart/form-data”.
Each part may be encoded and the “content-transfer-encoding” header supplied if the value of that part does not conform to the default encoding.

Where to use Multipart:

There are three basic options for enctype:
1. application/x-www-form-urlencoded (default)

2. multipart/form-data (for MIME content )

3. text-plain (not reliable)

The default content type/enctype is “application/x-www-form-urlencoded”. This is not efficient for sending large quantities of binary data or text containing non-ASCII characters. Multipart/form-data should be used for submitting forms that contain large files, non-ASCII data, and large binary data.

Moreover, multipart/form-data can be used for forms that are presented using representations like spreadsheets, Portable Document Format, etc. i.e other than HTML.

EXAMPLE: read carefully

Example: I am sending Text= “Danish” along with text file (file1.txt) and image file (file2.jpg)

Content-Type: multipart/form-data; boundary=Your_Boundary_String

— Your_Unique_Boundary_String

content-Disposition: form-data; name=”submit-name”

Danish

— Your_Unique_Boundary_String

content-Disposition: form-data; name=”files”

Content-Type: multipart/mixed; boundary=New_Boundary_String

— New_Boundary_String

content-Disposition: form-data; filename=”file1.txt”

Content-Type: text/plain

……..Contents of file1.txt……

— New_Boundary_String

content-Disposition: file; filename=”file2.jpg”

Content-Type: image/jpg

Content-Transfer-Encoding: binary

……..Contents of file2.jpg……

— New_Boundary_String

— Your_Unique_Boundary_String

Objective-C implementation for above example:

- (NSMutableRequest *)createMultipartRequestWithURL:(NSString *)urlString{

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]];

NSString *boundary = @”Your_Unique_Boundary_String”;

NSString *contentType = [NSString stringWithFormat:@”multipart/form-data; boundary = %@”,boundary];

[request addValue:contentType forHTTPHeaderField:@”Content-Type”];

[request setHTTPMethod:@”POST”];

[request setHTTPBody:[self createMulitpartBodyWithBoundary: boundary]];

return request;

}

- (NSData *)createMultipartRequestBodyWithBoudary:(NSString *)boundary

{

NSMutableData *body = [NSMutableData new];

[self appendObjectDataInMultipartBody:body withBoundary:boundary objectName:@”submit-name” objectData:self.submit-name.text];

[body appendData:[[NSString stringWithFormat:@”Content-Disposition: form-data; name=\”files\”\r\n\r\n%@”] dataUsingEncoding:NSUTF8StringEncoding]];

NSString *newBoundary = @”New_Boundary_String”;

[body appendData:[[NSString stringWithFormat:@”Content-Type: multipart/mixed; boundary =%@”,newBoundary] dataUsingEncoding:NSUTF8StringEncoding]];

[self appendFileDataInMultipartBody:body withBoundary:newBoundary fileName:@”file1.txt” contentType:@”text/plain” fileData:fileData];

[self appendFileDataInMultipartBody:body withBoundary:newBoundary fileName:@”file2.jpg” contentType:@”image/jpeg” fileData:fileData];

[body appendData: [[NSSTring stringWithFormat:@”\r\n- -%@\r\n”,boundary] dataUsingEncoding:NSUTF8StringEncoding]];

return body;

}

- (void)appendObjectDataInMultipartBody:(NSMutableData *)body withBoundary:(NSString *)boundary objectName:(NSString *)objectName objectData:(ID)objectData{

[body appendData: [[NSSTring stringWithFormat:@”\r\n- -%@\r\n”,boundary] dataUsingEncoding:NSUTF8StringEncoding]];

[body appendData:[[NSString stringWithFormat:@”Content-Disposition: form-data; name=\”%@\”\r\n\r\n%@”,objectName, objectData] dataUsingEncoding:NSUTF8StringEncoding]];

[body appendData: [[NSSTring stringWithFormat:@”\r\n- -%@\r\n”,boundary] dataUsingEncoding:NSUTF8StringEncoding]];

}

- (void)appendFileDataInMultipartBody:(NSMutableData *)body withBoundary:(NSString *)boundary fileName:(NSString *)name contentType:(NSString *)type fileData:(NSData *)data

{

[body appendData: [[NSSTring stringWithFormat:@”\r\n- -%@\r\n”,boundary] dataUsingEncoding:NSUTF8StringEncoding]];

[body appendData:[[NSString stringWithFormat:@”Content-Disposition: form-data; filename=\”%@\”,name] dataUsingEncoding:NSUTF8StringEncoding]];

[body appendData:[@”Content-Type: %@”,type dataUsingEncoding:NSUTF8StringEncoding]];

[body appendData: data];

[body appendData:[[NSString stringWithFormat:@”\r\n”] dataUsingEncoding:NSUTF8StringEncoding]];

[body appendData: [[NSSTring stringWithFormat:@”\r\n- -%@\r\n”,boundary] dataUsingEncoding:NSUTF8StringEncoding]];

}

References:

--

--

Mohd Danish Khan

iOS / Flutter Software Engineer, Machine Learning enthusiast