Como posso carregar uma foto para um servidor com o iPhone?

Estou escrevendo um aplicativo para iPhone que tira uma foto e depois a envia para um servidor. Como faço para enviar uma foto para um servidor com o Cocoa? Eu suponho que eu use o NSUrl em algum lugar.

Obrigado!

Cabeçalho:

@interface EPUploader : NSObject { NSURL *serverURL; NSString *filePath; id delegate; SEL doneSelector; SEL errorSelector; BOOL uploadDidSucceed; } - (id)initWithURL: (NSURL *)serverURL filePath: (NSString *)filePath delegate: (id)delegate doneSelector: (SEL)doneSelector errorSelector: (SEL)errorSelector; - (NSString *)filePath; @end 

A Principal:

 #import "EPUploader.h" #import  static NSString * const BOUNDRY = @"0xKhTmLbOuNdArY"; static NSString * const FORM_FLE_INPUT = @"uploaded"; #define ASSERT(x) NSAssert(x, @"") @interface EPUploader (Private) - (void)upload; - (NSURLRequest *)postRequestWithURL: (NSURL *)url boundry: (NSString *)boundry data: (NSData *)data; - (NSData *)compress: (NSData *)data; - (void)uploadSucceeded: (BOOL)success; - (void)connectionDidFinishLoading:(NSURLConnection *)connection; @end @implementation EPUploader /* *----------------------------------------------------------------------------- * * -[Uploader initWithURL:filePath:delegate:doneSelector:errorSelector:] -- * * Initializer. Kicks off the upload. Note that upload will happen on a * separate thread. * * Results: * An instance of Uploader. * * Side effects: * None * *----------------------------------------------------------------------------- */ - (id)initWithURL: (NSURL *)aServerURL // IN filePath: (NSString *)aFilePath // IN delegate: (id)aDelegate // IN doneSelector: (SEL)aDoneSelector // IN errorSelector: (SEL)anErrorSelector // IN { if ((self = [super init])) { ASSERT(aServerURL); ASSERT(aFilePath); ASSERT(aDelegate); ASSERT(aDoneSelector); ASSERT(anErrorSelector); serverURL = [aServerURL retain]; filePath = [aFilePath retain]; delegate = [aDelegate retain]; doneSelector = aDoneSelector; errorSelector = anErrorSelector; [self upload]; } return self; } /* *----------------------------------------------------------------------------- * * -[Uploader dealloc] -- * * Destructor. * * Results: * None * * Side effects: * None * *----------------------------------------------------------------------------- */ - (void)dealloc { [serverURL release]; serverURL = nil; [filePath release]; filePath = nil; [delegate release]; delegate = nil; doneSelector = NULL; errorSelector = NULL; [super dealloc]; } /* *----------------------------------------------------------------------------- * * -[Uploader filePath] -- * * Gets the path of the file this object is uploading. * * Results: * Path to the upload file. * * Side effects: * None * *----------------------------------------------------------------------------- */ - (NSString *)filePath { return filePath; } @end // Uploader @implementation EPUploader (Private) /* *----------------------------------------------------------------------------- * * -[Uploader(Private) upload] -- * * Uploads the given file. The file is compressed before beign uploaded. * The data is uploaded using an HTTP POST command. * * Results: * None * * Side effects: * None * *----------------------------------------------------------------------------- */ - (void)upload { NSData *data = [NSData dataWithContentsOfFile:filePath]; ASSERT(data); if (!data) { [self uploadSucceeded:NO]; return; } if ([data length] == 0) { // There's no data, treat this the same as no file. [self uploadSucceeded:YES]; return; } // NSData *compressedData = [self compress:data]; // ASSERT(compressedData && [compressedData length] != 0); // if (!compressedData || [compressedData length] == 0) { // [self uploadSucceeded:NO]; // return; // } NSURLRequest *urlRequest = [self postRequestWithURL:serverURL boundry:BOUNDRY data:data]; if (!urlRequest) { [self uploadSucceeded:NO]; return; } NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self]; if (!connection) { [self uploadSucceeded:NO]; } // Now wait for the URL connection to call us back. } /* *----------------------------------------------------------------------------- * * -[Uploader(Private) postRequestWithURL:boundry:data:] -- * * Creates a HTML POST request. * * Results: * The HTML POST request. * * Side effects: * None * *----------------------------------------------------------------------------- */ - (NSURLRequest *)postRequestWithURL: (NSURL *)url // IN boundry: (NSString *)boundry // IN data: (NSData *)data // IN { // from http://www.cocoadev.com/index.pl?HTTPFileUpload NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url]; [urlRequest setHTTPMethod:@"POST"]; [urlRequest setValue: [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundry] forHTTPHeaderField:@"Content-Type"]; NSMutableData *postData = [NSMutableData dataWithCapacity:[data length] + 512]; [postData appendData: [[NSString stringWithFormat:@"--%@\r\n", boundry] dataUsingEncoding:NSUTF8StringEncoding]]; [postData appendData: [[NSString stringWithFormat: @"Content-Disposition: form-data; name=\"%@\"; filename=\"file.bin\"\r\n\r\n", FORM_FLE_INPUT] dataUsingEncoding:NSUTF8StringEncoding]]; [postData appendData:data]; [postData appendData: [[NSString stringWithFormat:@"\r\n--%@--\r\n", boundry] dataUsingEncoding:NSUTF8StringEncoding]]; [urlRequest setHTTPBody:postData]; return urlRequest; } /* *----------------------------------------------------------------------------- * * -[Uploader(Private) compress:] -- * * Uses zlib to compress the given data. * * Results: * The compressed data as a NSData object. * * Side effects: * None * *----------------------------------------------------------------------------- */ - (NSData *)compress: (NSData *)data // IN { if (!data || [data length] == 0) return nil; // zlib compress doc says destSize must be 1% + 12 bytes greater than source. uLong destSize = [data length] * 1.001 + 12; NSMutableData *destData = [NSMutableData dataWithLength:destSize]; int error = compress([destData mutableBytes], &destSize, [data bytes], [data length]); if (error != Z_OK) { NSLog(@"%s: self:0x%p, zlib error on compress:%d\n",__func__, self, error); return nil; } [destData setLength:destSize]; return destData; } /* *----------------------------------------------------------------------------- * * -[Uploader(Private) uploadSucceeded:] -- * * Used to notify the delegate that the upload did or did not succeed. * * Results: * None * * Side effects: * None * *----------------------------------------------------------------------------- */ - (void)uploadSucceeded: (BOOL)success // IN { [delegate performSelector:success ? doneSelector : errorSelector withObject:self]; } /* *----------------------------------------------------------------------------- * * -[Uploader(Private) connectionDidFinishLoading:] -- * * Called when the upload is complete. We judge the success of the upload * based on the reply we get from the server. * * Results: * None * * Side effects: * None * *----------------------------------------------------------------------------- */ - (void)connectionDidFinishLoading:(NSURLConnection *)connection // IN { NSLog(@"%s: self:0x%p\n", __func__, self); [connection release]; [self uploadSucceeded:uploadDidSucceed]; } /* *----------------------------------------------------------------------------- * * -[Uploader(Private) connection:didFailWithError:] -- * * Called when the upload failed (probably due to a lack of network * connection). * * Results: * None * * Side effects: * None * *----------------------------------------------------------------------------- */ - (void)connection:(NSURLConnection *)connection // IN didFailWithError:(NSError *)error // IN { NSLog(@"%s: self:0x%p, connection error:%s\n", __func__, self, [[error description] UTF8String]); [connection release]; [self uploadSucceeded:NO]; } /* *----------------------------------------------------------------------------- * * -[Uploader(Private) connection:didReceiveResponse:] -- * * Called as we get responses from the server. * * Results: * None * * Side effects: * None * *----------------------------------------------------------------------------- */ -(void) connection:(NSURLConnection *)connection // IN didReceiveResponse:(NSURLResponse *)response // IN { NSLog(@"%s: self:0x%p\n", __func__, self); } /* *----------------------------------------------------------------------------- * * -[Uploader(Private) connection:didReceiveData:] -- * * Called when we have data from the server. We expect the server to reply * with a "YES" if the upload succeeded or "NO" if it did not. * * Results: * None * * Side effects: * None * *----------------------------------------------------------------------------- */ - (void)connection:(NSURLConnection *)connection // IN didReceiveData:(NSData *)data // IN { NSLog(@"%s: self:0x%p\n", __func__, self); NSString *reply = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]; NSLog(@"%s: data: %s\n", __func__, [reply UTF8String]); if ([reply hasPrefix:@"YES"]) { uploadDidSucceed = YES; } } @end 

Uso:

  [[EPUploader alloc] initWithURL:[NSURL URLWithString:@"http://yourserver.com/uploadDB.php"] filePath:@"path/to/some/file" delegate:self doneSelector:@selector(onUploadDone:) errorSelector:@selector(onUploadError:)]; 

Espero que o seguinte trecho de código funcione para você. Eu usei NSDateFormatter e NSDate para obter o nome exclusivo de cada vez para a imagem.

Nota: 'ImageUploadURL' é a string #define com o URL base, você precisa substituí-lo com o URL do seu servidor.

// Formato da data para o nome da imagem …

 NSDateFormatter *format = [[NSDateFormatter alloc] init]; [format setDateFormat:@"yyyyMMddHHmmss"]; NSDate *now = [[NSDate alloc] init]; NSString *imageName = [NSString stringWithFormat:@"Image_%@", [format stringFromDate:now]]; [now release]; [format release]; NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease]; [request setURL:[NSURL URLWithString:ImageUploadURL]]; [request setHTTPMethod:@"POST"]; /* Set Header and content type of your request. */ NSString *boundary = [NSString stringWithString:@"---------------------------Boundary Line---------------------------"]; NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary]; [request addValue:contentType forHTTPHeaderField: @"Content-Type"]; /* now lets create the body of the request. */ NSMutableData *body = [NSMutableData data]; [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"userfile\"; filename=\"%@.jpg\"\r\n", imageName] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithString:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[NSData dataWithData:UIImageJPEGRepresentation(image, 90)]]; [body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"geotag=%@&", [self _currentLocationMetadata]] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; // set body with request. [request setHTTPBody:body]; [request addValue:[NSString stringWithFormat:@"%d", [body length]] forHTTPHeaderField:@"Content-Length"]; // now lets make the connection to the web [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; 

Crie um NSURLRequest e, em seguida, use NSURLConnection para enviá-lo para o seu servidor.

Parece que a biblioteca Three20 tem suporte para POSTAR imagens para o servidor HTTP.

Veja TTURLRequest.m

E é lançado sob a licença Apache 2.0.

 - (void) uploadImage :(NSString *) strRequest { if([appdel checkNetwork]==TRUE) { NSString *urlString =[NSString stringWithFormat:@"Enter Url........."]; NSLog(@"Upload %@",urlString); // setting up the request object now isUploadImage=TRUE; totalsize=[[strRequest dataUsingEncoding:NSUTF8StringEncoding]length]; NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease]; [request setURL:[NSURL URLWithString:urlString]]; [request setHTTPMethod:@"POST"]; NSString *boundary = [NSString stringWithString:@"_1_19330907_1317415362628"]; NSString *contentType = [NSString stringWithFormat:@"multipart/mixed; boundary=%@",boundary]; [request setValue:contentType forHTTPHeaderField: @"Content-Type"]; [request setValue:@"text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2" forHTTPHeaderField:@"Accept"]; [request setValue:@"2667" forHTTPHeaderField:@"Content-Length"]; /* now lets create the body of the post */ NSMutableData *body = [NSMutableData data]; [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithString:@"Content-Type: application/json\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; //[body appendData:[NSData dataWithData:imageData]]; [body appendData:[strRequest dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; // setting the body of the post to the reqeust [request setHTTPBody:body]; theConnection=[[NSURLConnection alloc] initWithRequest:request delegate:self]; if (theConnection) webData = [[NSMutableData data] retain]; else NSLog(@"No Connection"); } } 

Se você deseja enviar várias imagens, esta demonstração é uma boa opção.