顯示具有 http 標籤的文章。 顯示所有文章
顯示具有 http 標籤的文章。 顯示所有文章

2011/07/19

透過NSURLConnection和NSMutableURLRequest上傳/POST一個檔案

直接來看code
NSURLConnection *conn;
NSMutableData *tempData;  /* Store response */

- (void)uploadFile {
    NSString *boundary = @"0xKhTmLbOuNdArY";
    NSData *imgData = UIImageJPEGRepresentation(image.image, 90);  /* Image data come from UIImageView */
    NSString *urlString = @"http://my_server/upload.php";
    NSURL *url = [[NSURL alloc]initWithString:urlString];

    /* Set up request */
    NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
    [urlRequest setHTTPMethod:@"POST"];
    [urlRequest setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary] forHTTPHeaderField:@"Content-Type"];

    /* Prepare content part */
    NSMutableData *postData = [NSMutableData dataWithCapacity:[imgData length] + 512];
    [postData appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [postData appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"file.bin\"\r\n\r\n", @"image"] dataUsingEncoding:NSUTF8StringEncoding]];
    [postData appendData:imgData];
    [postData appendData: [[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];

    /* Assign content part */
    [urlRequest setHTTPBody:postData];

    tempData = [NSMutableData alloc];
    conn = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
}


Prepare 4 delegate
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    [conn release];
    NSLog(@"Error occur");
}

- (void)connection: (NSURLConnection *)connection didReceiveResponse: (NSURLResponse *)aResponse {
    NSInteger status = (NSInteger)[(NSHTTPURLResponse *)aResponse statusCode];
    NSLog(@"%d", status);
}

-(void) connection:(NSURLConnection *)connection didReceiveData: (NSData *) incomingData {
 [tempData appendData:incomingData];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    NSString *loadData = [[NSMutableString alloc] initWithData:tempData encoding:NSUTF8StringEncoding];    
    NSLog(@"%@", loadData);
}


Server - PHP sample code
<?php 
    if (isset($_FILES["image"]))
    {
        print_r($_FILES["image"]);
    }
?>

參考資料
CocoaDev: HTTPFileUploadSample

2011/07/12

在iPhone上建立HTTP連線(GET/POST)

HTTP Get
Create request
NSString *str = @"http://my_server/get.php?name=brian&gender=male";
NSString *str_enc = [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [[NSURL URLWithString:str_enc] retain];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];

Prepare delegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;


HTTP Post
NSString *content = @"name=brian&gender=male";
NSData *postData = [content dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]];
 
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:@"http://my_server/post.php"]];
[request setHTTPMethod:@"POST"];

/* Header */
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];

/* Content */
[request setHTTPBody:postData];

connect = [[NSURLConnection alloc] initWithRequest:request delegate:self];
// 跟GET一樣設定4組delegate去接response

參考資料

2011/06/20

HTTP server over libevent - sample code (2)

加入一些parse的function,可以得到request的method、URI、header、body、path

#include 
#include 
#include 
#include 
#include 

#define SVR_IP                         "127.0.0.1"
#define SVR_PORT                       8080

void dump_cb (struct evhttp_request *req, void *arg) {
    const char        *uri;
    struct evkeyvalq  *headers;
    struct evkeyval   *header;
    struct evbuffer   *evbuf;
    struct evhttp_uri *ev_uri;
    
    /* Get method */
    switch (evhttp_request_get_command(req)) {
        case EVHTTP_REQ_GET: 
            printf("Request method=[GET]\n");
            break;
        case EVHTTP_REQ_POST:
            printf("Request method=[POST]\n");
            break;
        default:
            printf("Request method=[others]\n");
            break;
    }
    
    /* Get path */
    uri = evhttp_request_get_uri(req);
    printf("Request uri=[%s]\n",  uri);
    
    /* Get header */
    printf("Headers:\n");
    headers = evhttp_request_get_input_headers(req);
    for (header = headers->tqh_first; header;
        header = header->next.tqe_next) {
        printf("  %s: %s\n", header->key, header->value);
    }
        
    /* Get body */
    evbuf = evhttp_request_get_input_buffer(req);
    printf("Body:\n");
    while (evbuffer_get_length(evbuf)) {
        int  size;
        char buf[128];
        
        memset(buf, 0, sizeof(buf));
        size = evbuffer_remove(evbuf, buf, sizeof(buf) - 1);
        printf("  %s\n", buf);
    }
    
    /* */
    ev_uri = evhttp_uri_parse(uri);
    if (ev_uri) {
        const char *path;
        char       *decoded_path;
        
        path = evhttp_uri_get_path(ev_uri);
        decoded_path = evhttp_uridecode(path, 0, NULL);
        printf("Request path=[%s]\n", decoded_path);
        
        /* Free resource */
        free(decoded_path);
        evhttp_uri_free(ev_uri);
    }
    
    /* Response */
    evhttp_send_reply(req, HTTP_OK, "OK", NULL);
}

int main (int argc, char **argv) {
    struct event_base *evbase;
    struct evhttp     *evhttp;

    /* Init event base */
    if ((evbase = event_base_new()) == NULL) {
        printf("event_base_new() failed\n");
        return -1;
    }

    /* Init evhttp */
    if ((evhttp = evhttp_new(evbase)) == NULL) {
        printf("evhttp_new() failed\n");
        return -1;
    }

    /* Set server IP, port */
    if (evhttp_bind_socket(evhttp, SVR_IP, SVR_PORT) == -1) {
        printf("evhttp_bind_socket() failed\n");
        return -1;
    } else {
        printf("Listening on [%s:%d]\n", SVR_IP, SVR_PORT);
    }
    
    /* Set timeout */
    evhttp_set_timeout(evhttp, 10);
    
    /* Set a callback for default path */
    evhttp_set_gencb(evhttp, dump_cb, NULL);

    /* Enter event loop */
    event_base_dispatch(evbase);

    /* Free resource */
    evhttp_free(evhttp);
    event_base_free(evbase);
    
    return 0;
}



Compile and run
$ gcc -g -Wall -o httpd httpd.c -levent -I/opt/libevent-2.0.12-stable/include/ -L/opt/libevent-2.0.12-stable/lib/
$ LD_LIBRARY_PATH=/opt/libevent-2.0.12-stable/lib ./httpd
Listening on [127.0.0.1:8080]

Request method=[GET]
Request uri=[/test.php?name=kevin&sex=male]
Headers:
  User-Agent: Wget/1.11.4 Red Hat modified
  Accept: */*
  Host: 127.0.0.1:8080
  Connection: Keep-Alive
Body:
Request path=[/test.php]

Request method=[POST]
Request uri=[/test.php]
Headers:
  User-Agent: Wget/1.11.4 Red Hat modified
  Accept: */*
  Host: 127.0.0.1:8080
  Connection: Keep-Alive
  Content-Type: application/x-www-form-urlencoded
  Content-Length: 19
Body:
  name=sylar&sex=male
Request path=[/test.php]


try to send a request to server...
# Get
$wget -q -O - 'http://127.0.0.1:8080/test.php?name=sylar&sex=male'

# Post
$wget -q -O - --post-data='name=sylar&sex=male' http://127.0.0.1:8080/test.php

2011/06/17

HTTP server over libevent - sample code (1)

使用libevent HTTP API寫一個簡易的server。

#include 
#include 
#include 

#define SVR_IP                         "127.0.0.1"
#define SVR_PORT                       8080

void specific_cb (struct evhttp_request *req, void *arg) {
    struct evbuffer *evbuf;
    
    if ((evbuf = evbuffer_new()) == NULL) {
        printf("evbuffer_new() failed");
        evhttp_send_reply(req, HTTP_INTERNAL, "Internal error", NULL);
        return;
    }

    /* Body */
    evbuffer_add_printf(evbuf, "It's work!");
    
    /* Response */
    evhttp_send_reply(req, HTTP_OK, "OK", evbuf);
    
    /* Free resource */
    evbuffer_free(evbuf);
}

void generic_cb (struct evhttp_request *req, void *arg) {

    /* Response */
    evhttp_send_reply(req, HTTP_NOTFOUND, "Not found", NULL);
}

int main (int argc, char **argv) {
    struct event_base *evbase;
    struct evhttp     *evhttp;

    /* Init event base */
    if ((evbase = event_base_new()) == NULL) {
        printf("event_base_new() failed\n");
        return -1;
    }

    /* Init evhttp */
    if ((evhttp = evhttp_new(evbase)) == NULL) {
        printf("evhttp_new() failed\n");
        return -1;
    }

    /* Set server IP, port */
    if (evhttp_bind_socket(evhttp, SVR_IP, SVR_PORT) == -1) {
        printf("evhttp_bind_socket() failed\n");
        return -1;
    } else {
        printf("Listening on [%s:%d]\n", SVR_IP, SVR_PORT);
    }
    
    /* Set a callback for specific path */
    if (evhttp_set_cb(evhttp, "/test", specific_cb, NULL) < 0) {
        printf("evhttp_set_cb() failed\n");
        return -1;
    }
    
    /* Set a callback for default path */
    evhttp_set_gencb(evhttp, generic_cb, NULL);

    /* Enter event loop */
    event_base_dispatch(evbase);

    /* Free resource */
    evhttp_free(evhttp);
    event_base_free(evbase);
    
    return 0;
}
Compile and run
$ gcc -g -Wall -o httpd httpd.c -levent -I/opt/libevent-2.0.12-stable/include/ -L/opt/libevent-2.0.12-stable/lib/
$ LD_LIBRARY_PATH=/opt/libevent-2.0.12-stable/lib ./httpd
Listening on [127.0.0.1:8080]
try to send a request to server...
$ wget -q -O - http://127.0.0.1:8080/test
$ wget -S -O - http://127.0.0.1:8080/xxx
不知道為什麼我用2.0.10-stable版本跑會有下列warning,用2.0.12-stable就沒問題了。
[warn] evhttp_connection_base_new: bufferevent_new failed: No such file or directory
[warn] evhttp_get_request: cannot get connection on 9: No such file or directory