ПРОГРАММИРОВАНИЕ ПОД IPHONE, IPAD OBJECTIVE-C часть 2

Отправка файлов на сервер

Было много написано о том как получать данные с сервера, но ни слова — как сделать отправку. В этом примере мы «заткнем» эту дыру. Для начал нам понадобиться проект с шаблона Single View Application, а назовем мы его DataSender.

 

Отправлять серверу мы будем логотип этого же сайта (ссылка на файл). Скачайте картинку и добавьте ее в проект (вы можете добавить любой другой файл по желанию). Теперь перейдем к процессу программирования. Нам понадобится переменная, которая будет хранить ответ от сервреа. Эта переменная типа NSMutableData, я назвал ее infoData. Вот так выглядет файл ViewController.h:

 

<code data-result="[object Object]">#import &lt;UIKit/UIKit.h&gt;

@interface ViewController : UIViewController

@property (nonatomic, retain) NSMutableData *infoData;

@end</code>

 

Соответственно, внесем изменения в файл ViewController.m:

 

<code data-result="[object Object]">#import "ViewController.h"

@implementation ViewController

@synthesize infoData;

- (void)dealloc
{
    self.infoData = nil;
    [super dealloc];
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSString *url = @"http://www.imaladec.net/phpExamples/uploader.php";
    url = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

    NSMutableURLRequest *theRequest=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]
                                                            cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                        timeoutInterval:60.0f];
    [theRequest setHTTPMethod:@"POST"];

    NSString *boundary = @"---------------------------14737809831466499882746641449";
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
    [theRequest addValue:contentType forHTTPHeaderField:@"Content-Type"];

    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"logo" ofType:@"png"];
    NSData *imageData = [NSData dataWithContentsOfFile:filePath];

    NSMutableData *body = [NSMutableData data];
    [body appendData:[[NSString stringWithFormat:@"--%@
", boundary] 
                      dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[@"Content-Disposition: attachment; name="userfile"; filename="image.png"
" 
                      dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[@"Content-Type: application/octet-stream

" 
                      dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:imageData];
    [body appendData:[@"
" dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"--%@--
", boundary] 
                      dataUsingEncoding:NSUTF8StringEncoding]];

    [theRequest setHTTPBody:body];

    NSURLConnection *connection = [NSURLConnection connectionWithRequest:theRequest delegate:self];
    if (connection) {
        self.infoData = [NSMutableData data];
    } else {
        NSLog(@"Connection failed");
    }
}

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

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

@end</code>

 

Код в метод viewDidLoad очень похож на код с примера Закачка данных. Основные отличия начинаются после строки [theRequest setHTTPMethod:@»POST»];. Как раз в ней мы устанавливаем метод запроса. Затем устанавливаем тип данных, которые собераемся отправлять, считываем ранее добавленный файл и формируем тело запроса. В процессе формирования тела запроса следует обратить внимание на строку filename=»image.png», именно в ней мы устанавливаем имя файла, который будем отправлять. После того как тело сформировано, в строке [theRequest setHTTPBody:body]; передаем его запросу. А дальше, как прежде — создаем и запускаем новое соединение.

 

По окончанию успешной загрузки сервер вернет ссылку на файл (она будет храниться в переменной infoData, которую мы преобразовываем в строку и выводим в консоль). Но чтобы все работало верно — слудет провести некоторые изменения на сервере. Вот так выглядит файл uploader.php:

 

<code data-result="[object Object]">&lt;?php
	$uploaddir = './upload-files/decode/';
	$file = basename($_FILES['userfile']['name']);
	$uploadfile = $uploaddir . $file;

	if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
		echo "http://www.imaladec.net/upload-files/decode/{$file}";
	}
?&gt;</code>

 

Значение переменной uploaddir вы можете установить свое (я указал папку, которая периодически очищается).

 

Исходный код этого проекта можно скачать здесь.