1. Welcome to the new MacRumors forums. See our announcement and read our FAQ

Sending pictures with NSURLRequest

Discussion in 'Mac Programming' started by Kozmicstu, Feb 4, 2008.

  1. macrumors newbie

    #1
    Hi

    I'm trying to send a multipart/form-data 'POST' request using NSURLRequest, including several keys, but also an image. I'm not particularly knowledgeable on HTTP request (and pretty new to Cocoa, to be honest...)

    If you want to know what it's for, right now I'm trying to work against the Tumblr API to post a photo to a Tumblelog from a Cocoa app. I've managed to make text posts from the app, but I can't work out how to do a photo post.

    I've been looking on forums and there's a couple of people with really long-winded solutions but I haven't managed to get any of them working. The connection starts and then a message comes back saying 'posts cannot be empty', suggesting that the authentication is fine, but it's not receiving the data part of the message

    Anyway, I'd be grateful for any help, if anyone knows how to make this happen :)

    Stu
     
  2. Moderator emeritus

    kainjow

    #2
  3. macrumors newbie

    #3
    Thanks very much for that. I had found one of them before and tried it, but I gave it another go and got it working perfectly. I think I might have been leaving keys out somewhere along the way or something...

    Anyway, here's the (probably messy) code I used in the end, for posterity's sake (or for anyone else who wants to do this...)

    Code:
    - (BOOL)sendPhotoToTumblr:(NSString *)photo withCaption:(NSString *)caption;
    {
    	//get image data from file
    	NSData *imageData = [NSData dataWithContentsOfFile:photo];	
    	//stop on error
    	if (!imageData) return NO;
    	
    	//Create dictionary of post arguments
    	NSArray *keys = [[NSArray alloc] initWithObjects:@"email",@"password",@"type",@"caption",nil];
    	NSArray *objects = [[NSArray alloc] initWithObjects:
    			[NSString stringWithFormat:@"%@",CFPreferencesCopyAppValue(CFSTR("TumblrEmail"), kCFPreferencesCurrentApplication)],
    			[NSString stringWithFormat:@"%@",CFPreferencesCopyAppValue(CFSTR("TumblrPassword"), kCFPreferencesCurrentApplication)],
    			@"photo", caption, nil];
    	NSDictionary *keysDict = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];
    	
    	//create tumblr photo post
    	NSURLRequest *tumblrPost = [self createTumblrRequest:keysDict withData:imageData];
    	
    	//send request, return YES if successful
    	tumblrConnection = [[NSURLConnection alloc] initWithRequest:tumblrPost delegate:self];
    	if (!tumblrConnection) {
    		NSLog(@"Failed to submit request");
    		return NO;
    	} else {
    		NSLog(@"Request submitted");
    		receivedData = [[NSMutableData data] retain];
    		return YES;
    	}
    }
    
    
    -(NSURLRequest *)createTumblrRequest:(NSDictionary *)postKeys withData:(NSData *)data
    {
    	//create the URL POST Request to tumblr
    	NSURL *tumblrURL = [NSURL URLWithString:@"http://www.tumblr.com/api/write"];
    	NSMutableURLRequest *tumblrPost = [NSMutableURLRequest requestWithURL:tumblrURL];
    	[tumblrPost setHTTPMethod:@"POST"];
    	
    	//Add the header info
    	NSString *stringBoundary = [NSString stringWithString:@"0xKhTmLbOuNdArY"];
    	NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",stringBoundary];
    	[tumblrPost addValue:contentType forHTTPHeaderField: @"Content-Type"];
    	
    	//create the body
    	NSMutableData *postBody = [NSMutableData data];
    	[postBody appendData:[[NSString stringWithFormat:@"--%@\r\n",stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
    	
    	//add key values from the NSDictionary object
    	NSEnumerator *keys = [postKeys keyEnumerator];
    	int i;
    	for (i = 0; i < [postKeys count]; i++) {
    		NSString *tempKey = [keys nextObject];
    		[postBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",tempKey] dataUsingEncoding:NSUTF8StringEncoding]];
    		[postBody appendData:[[NSString stringWithFormat:@"%@",[postKeys objectForKey:tempKey]] dataUsingEncoding:NSUTF8StringEncoding]];
    		[postBody appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
    	}
    
    	//add data field and file data
    	[postBody appendData:[[NSString stringWithString:@"Content-Disposition: form-data; name=\"data\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    	[postBody appendData:[[NSString stringWithString:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    	[postBody appendData:[NSData dataWithData:data]];
    	[postBody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",stringBoundary] dataUsingEncoding:NSUTF8StringEncoding]];
    	
    	//add the body to the post
    	[tumblrPost setHTTPBody:postBody];
    
    	return tumblrPost;
    }
     
  4. Moderator emeritus

    kainjow

    #4
    Make sure you release or autorelease your keys, objects, and keysDict variables. You're leaking memory if you don't (unless you have GC on).
     
  5. macrumors newbie

    #5
    hi , im also sending images using NSMutableURLRequest with post method to my remote web page which is in ASP VB.net.

    I have seen one tutroial which can upload a image from iphone to remote web(php page)

    http://iphone.zcentric.com/2008/08/29/post-a-uiimage-to-the-web/#comment-8145

    I am not getting how can I retrieve the image in my VB.net page??

    Can any one suggest how can I do that ??

    Thanks & Regards,
    Narendar
     
  6. macrumors newbie

    #6
    This post has helped me out a ton!

    The one thing I can't figure out is how to make a module appear for users to enter their email / pass to log into tumblr to share the image.

    any tips on this?
     

Share This Page