How can I upload a photo to a server with the iPho

2018-12-31 15:25发布

问题:

I\'m writing an iPhone app that takes a photo and then uploads it to a server. How do I upload a photo to a server with Cocoa? I suppose I use NSUrl somewhere.

Thanks!

回答1:

Header:

@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

Main:

#import \"EPUploader.h\"
#import <zlib.h>

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

Usage:

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


回答2:

Hope following code snippet will work for you. I have used NSDateFormatter and NSDate to get unique name each time for the image.

Note: \'ImageUploadURL\' is the string #define with the base url, you need to replace it with your server url.

//Date format for Image Name...

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];


回答3:

Create an NSURLRequest and then use NSURLConnection to send it off to your server.



回答4:

Looks like Three20 library has support for POSTing images to HTTP server.

See TTURLRequest.m

And it\'s released under Apache 2.0 License.



回答5:

- (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\");    
}

}


回答6:

If you want to upload multiple images then this demo is good option.