Objective-C 画像をリサイズしてサーバにUpload

#やりたかったこと
よくあるプロフィール写真を選択して、トリミングして設定。がやりたかったので
実装してみました。今回は一つの画像だけでよかったけど
検索したサイトの実装の流れで、以下のようになってしまった。

テキストのPOST送信と画像のUploadをマルチパートで行う。
NSURLSessionDataTaskデリゲートでの実装でなく、
Blocksで成功/エラーのコールバックを返す。
なお、画像はUIImagePickerControllerでアルバムから選択し
トリミングとリサイズした画像を使用する。
アルバムからでなく、カメラで撮影したものを使いたければ、UIImagePickerControllerSourceTypePhotoLibraryの箇所をUIImagePickerControllerSourceTypeCameraと変更すればOKです

POST送信については、[この辺](http://chicketen.blog.jp/archives/1282033.html)を参考にしました。
#自作のReqHTTPクラス

```objc

//ReqHTTP.h
#import <CoreImage/CoreImage.h>
@interface ReqHTTP : NSObject
- (void)postMultiDataWithTextDictionary:(NSDictionary*)textDictionary
                        imageDictionary:(NSDictionary*)imageDictionary
                                    url:(NSURL*)url done:(void(^)(NSDictionary *responseData)) doneHandler fail:(void(^)(NSInteger status)) failHandler;
@end
 
//ReqHTTP.m
@implementation ReqHTTP
{
    void (^requestDoneHandler)(NSDictionary *data);
    void (^requestFailHandler)(NSInteger status);
}
- (void)postMultiDataWithTextDictionary:(NSDictionary*)textDictionary
                        imageDictionary:(NSDictionary*)imageDictionary
                                    url:(NSURL*)url done:(void(^)(NSDictionary *responseData)) doneHandler fail:(void(^)(NSInteger status)) failHandler
{
    requestDoneHandler = doneHandler;
    requestFailHandler = failHandler;
    
    NSURLSessionConfiguration* config = [NSURLSessionConfiguration defaultSessionConfiguration];
    NSString* boundary = @"1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    config.HTTPAdditionalHeaders =
    @{
      @"Content-Type" : [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary]
      };
 
    NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
    
    NSURLSession *session = [NSURLSession sessionWithConfiguration:config];
    // postデータの作成
    NSMutableData* data = [NSMutableData data];
    // テキスト部分の設定
    for (id key in [textDictionary keyEnumerator])
    {
        NSString* value = [textDictionary valueForKey:key];
        
        [data appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
        [data appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data;"] dataUsingEncoding:NSUTF8StringEncoding]];
        [data appendData:[[NSString stringWithFormat:@"name=\"%@\"\r\n\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]];
        [data appendData:[[NSString stringWithFormat:@"%@\r\n", value] dataUsingEncoding:NSUTF8StringEncoding]];
    }
    
    // 画像の設定
    for (int i = 0; i < [imageDictionary count]; i++)
    {
        NSString* key = [[imageDictionary allKeys] objectAtIndex:i];
        NSData* value = [imageDictionary valueForKey:key];
        NSString* name = [NSString stringWithFormat:@"upload_file%d", i];
        
        [data appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
        [data appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data;"] dataUsingEncoding:NSUTF8StringEncoding]];
        [data appendData:[[NSString stringWithFormat:@"name=\"%@\";", name] dataUsingEncoding:NSUTF8StringEncoding]];
        [data appendData:[[NSString stringWithFormat:@"filename=\"%@\"\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]];
        [data appendData:[[NSString stringWithFormat:@"Content-Type: image/jpeg\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
        [data appendData:value];
        [data appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    }
    
    // 最後にバウンダリを付ける
    [data appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    request.HTTPMethod = @"POST";
    request.HTTPBody = data;
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        [session invalidateAndCancel];//メモリリーク対策
        if(error){
            requestFailHandler(-1);
        }else{
            NSError *err = nil;
            NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data
                                                                 options:NSJSONReadingMutableContainers
                                                                   error:&err];
            if (err) {
                requestFailHandler(-1);
                return;
            }
            requestDoneHandler(json);
        }
        
    }];
    
    [task resume];
}
@end
```

#写真の選択

```objc

//viewController.h
@interface viewController : UIViewController<UINavigationControllerDelegate, UIImagePickerControllerDelegate>
@end
 
//viewController.m
@implementation viewController
{
       UIImage *resizedImage;
}
 
- (void)photoSelect{
   UIImagePickerController *picker = [[UIImagePickerController alloc] init];
   picker.delegate = self;
   picker.allowsEditing = YES;//写真選択後編集
   if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypePhotoLibrary]== NO){
        NSLog(@"Photo Library not available.");
        return;
   }
   picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
   [self presentViewController:picker animated:YES completion:nil];
 
}
 
//写真を選択/編集完了
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
    
    UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
    if(!image){
        image = [info objectForKey:UIImagePickerControllerOriginalImage];
    }
    //保持
    resizedImage = [self resizedImage:image width:100 height:100];
    
    [self dismissViewControllerAnimated:YES completion:NULL];
}
 
//画像をリサイズ
- (UIImage *)resizedImage:(UIImage *)image width:(CGFloat)width height:(CGFloat)height
{
    //UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), NO, [[UIScreen mainScreen] scale]);
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), NO, 1.0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetInterpolationQuality(context, kCGInterpolationDefault);
    
    [image drawInRect:CGRectMake(0.0, 0.0, width, height)];
    
    UIImage *resizedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return resizedImage;
}
```
#アップロード処理
```objc
 -(void)upload
{
     NSURL *url = [NSURL URLWithString:@"http://xxxxx/upload.php"];
     NSData *imageData = [[NSData alloc] initWithData:UIImageJPEGRepresentation(thumb.image, 1.0)];
 
     NSMutableDictionary* texts = [NSMutableDictionary dictionary];
     NSMutableDictionary* images = [NSMutableDictionary dictionary];
 
     [texts setObject:@"値" forKey:@"キー"];//複数ある場合はこれを追加
     [images setObject:imageData forKey:@"thumbnail.jpg"];//複数ある場合はこれを追加
     
     ReqHTTP *reqHTTP = [[ReqHTTP alloc] init];
     [reqHTTP postMultiDataWithTextDictionary:texts
                                 imageDictionary:images
                                             url:url
                                            done:^(NSDictionary *responseData) {
                                                NSInteger status = [[responseData objectForKey:@"status"] integerValue];
                                                if (status < 0) {
                                                    NSLog(@"画像のUploadに失敗");
                                                    return;
                                                }
                                                //成功
                                                NSLog(@"success %@", responseData);
                                                
                                            } fail:^(NSInteger status) {
                                                NSLog(@"画像のUploadに失敗");
                                            }];
}
```

#PHP
※Uploadエラー処理などは省略。
[この辺](http://qiita.com/mpyw/items/73ee77a9535cc65eff1e)が参考になるかも

```php

<?php
    $idx = count($_FILES) - 1;
    //今回は1つのみの画像Uploadだが
    //複数の場合はforで回して取得
    $tmp_path = $_FILES['upload_file'.$idx]['tmp_name'];
    $target_path = 'upload/';//保存ディレクトリ
    $target_path = $target_path.basename($_FILES['upload_file'.$idx]['name']);
    //→upload/thumbnail.jpg
 
    //一時保存画像を保存デジレクトリに移動
    if(move_uploaded_file($tmp_path, $target_path)){
        //保存成功
        echo json_encode(array(
            'status' => 0
        ));
        return;
    }
    //ここでは、失敗の場合statusにマイナス値を返している
    echo json_encode(array(
        'status' => -1
    ));
?>
```

PHPはよくわからないので、コードがダサいかもしれません。
あしからず