views:

1375

answers:

5

Hello!

I've just started development on Macs and have found Cocoa to be a useful and thoughtful framework, but its HTTP functionality has me puzzled.

I have an NSURLConnection object to download a file from my webserver using the HTTP GET method. NSURLConnect's asynchronous connection is great, I get plenty of feedback, I get each chunk received as a new NSData object that I can use to atomically rebuild the file on the client end and, importantly, provide the user with a progress report: [myData length].

Uploads, however, are nowhere near as neat. You can either stick a synchronous request in its own thread or call an asynchronous request (which I believe spawns its own thread), but neither provide you with any useful feedback. There's no delegates to request data or even let me know when data is being sent. Presumably this limits me to files smaller than available memory.

My question is, therefore, is there a simple and elegant solution to HTTP POST file uploads using Cocoa that provides a good deal of feedback and the ability to read files part-by-part, rather than all at once? Or should I write my own class from low-level networking functionality?

Thanks!

+1  A: 
sehugg
+1  A: 

Unfortunately, you're quite correct that NSURLConnection is weak here. The most flexible approach that I would recommend is CocoaAsyncSocket. It means rolling your own HTTP, which is unfortunate, but in most cases not that difficult. CocoaHTTPServer demonstrates how to build a full HTTP server on top of CocoaAsyncSocket, and may have a lot of useful code for your problem. I've found both of these very useful.

Another approach that may be worth investigating is WebKit. Create an invisible WebView, and loadRequest: a POST. I haven't dug into whether the estimatedChange notification system includes the time to upload or only the time to download, but it's worth a try.

Rob Napier
+1  A: 

You can take a look at the HTTPMessage section of my toolkit repository on github for a simple ObjC wrapper around CFHTTPMessageRef; among other things it'll hand you an NSInputStream object, which saves you thinking about plain-C callback functions.

Depending on what you're reading, you may want to take a look at the StreamingXMLParser section of the same repository for an XML (and HTML) parser which will parse data directly from said NSInputStream on your behalf.

Jim Dovey
+5  A: 

You may want to look at the ASIHTTPRequest framework. I haven't used it for uploading but it looks like it has more feedback and the usage is pretty straightforward.

bbrown
+1  A: 

ASIHTTPRequest was originally designed just for this purpose (tracking POST progress), since in the 2.x API, this isn't possible with NSURLConnection. It will definitely be easier to integrate than rolling your own with CFNetwork, and you get lots of other stuff for free (e.g. progress tracking across multiple requests, resuming downloads etc). :)

If the files you are uploading are large, be sure to look at the options for streaming directly from disk, so you don't have to hold the data in memory.

pokeb