Online Book Reader

Home Category

iOS Recipes - Matt Drance [67]

By Root 232 0

NSURLResponse *response = nil;

NSError *error = nil;

NSData *responseData = [NSURLConnection sendSynchronousRequest:postRequest

returningResponse:&response

error:&error];


Work asynchronously!

The BasicHTTPPost project accompanying this chapter uses a synchronous connection to demonstrate the POST. This is merely to demonstrate the solution with as few lines as possible, since the focus is on building the request itself. Apple strongly recommends using NSURLConnection in asynchronous mode.


Now you just need to test all this work. The BasicHTTPPost project includes a simple WEBrick servlet[4] that will receive POST methods and echo the output back. To run it, just navigate to the directory containing webserver.rb and type ruby webserver.rb. You should see some output indicating the server has started. To verify the server is running, drag the local form.html file into a browser, fill out the form, submit it, and check the response. Once you’ve verified the static HTML form works, run BasicHTTPPost and see what happens when you enter the same information into the iPhone app.

So there you have it...a straightforward and reusable mechanism for building form-based POST requests on demand.

Recipe 34 Upload Files Over HTTP

Problem

In the previous chapter, we discussed submitting form data in an HTTP POST using NSURLConnection and a custom NSMutableURLRequest subclass that hosted the HTTP body. With file/photo/video sharing on the rise, however, simple forms won’t always cut it. So, how do we upload a file to a website from Cocoa?

Solution

If we adopt a web API that accepts files, we’re almost certainly going to be asked to perform a multipart POST. This still involves setting data (lots of it being text) to the HTTP body, but it is much more complicated than posting a simple URL-encoded body string.

As RFC 1867[5] and RFC 1341[6] explain, a multipart body involves a combination of traditional form fields and binary file data, separated by an arbitrary “boundary” string. Here’s what a multipart body for a username, password, and JPEG upload might look like:

--d0ntcr055t3h57r33m2

Content-Disposition: form-data; name="username"

tyler

--d0ntcr055t3h57r33m2

Content-Disposition: form-data; name="password"

durden

--d0ntcr055t3h57r33m2

Content-Disposition: form-data; name="media"; filename="foo.jpg"

Content-Type: image/jpeg

--d0ntcr055t3h57r33m2

We’ve cut out the actual JPEG data, but as you can imagine, it’s quite noisy. This giant string is our HTTP body. The boundary string, d0ntcr055t3h57r33m2, is defined in the request header. Formatting this body with the boundary, the content-disposition headers, the line breaks, and the data itself is our responsibility. This can get very messy very quickly, and one wrong piece can spoil the entire upload.

Our goal is to add some sanity to this process so we don’t have to reinvent the wheel every time we’re ready to upload a file.


Uploading Multiple Files

This chapter covers uploading a single file with a multipart/form-data content type. Other servers and APIs may require a combination of multipart/form-data and multipart/mixed data. Between the examples in RFC 1867 and ideally the server’s documented requirements, it should be easy to extend this code to fit your needs.


Once again, we declare a subclass of NSMutableURLRequest—this time called PRPMultipartPOSTRequest. The class declares a dictionary for traditional key-value form parameters, which you can configure as you need. There’s also an HTTP boundary property for use in the POST body. You should always set a fairly unique boundary when performing a multipart upload.

MultipartHTTPPost/PRPMultipartPOSTRequest.h

@property (nonatomic, copy) NSString *HTTPBoundary;

@property (nonatomic, retain) NSDictionary *formParameters;

Next, we have a method for setting the file to upload. It requires a content type, a form variable name, and a destination filename on the server.

MultipartHTTPPost/PRPMultipartPOSTRequest.h

- (void)setUploadFile:(NSString *)path

contentType:(NSString

Return Main Page Previous Page Next Page

®Online Book Reader