#やりたかったこと
よくあるプロフィール写真を選択して、トリミングして設定。がやりたかったので
実装してみました。今回は一つの画像だけでよかったけど
検索したサイトの実装の流れで、以下のようになってしまった。
テキストのPOST送信と画像のUploadをマルチパートで行う。
NSURLSessionDataTaskデリゲートでの実装でなく、
Blocksで成功/エラーのコールバックを返す。
なお、画像はUIImagePickerControllerでアルバムから選択し
トリミングとリサイズした画像を使用する。
アルバムからでなく、カメラで撮影したものを使いたければ、UIImagePickerControllerSourceTypePhotoLibraryの箇所をUIImagePickerControllerSourceTypeCameraと変更すればOKです
POST送信については、この辺を参考にしました。
#自作のReqHTTPクラス
//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
#写真の選択
//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;
}
#アップロード処理
-(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エラー処理などは省略。
この辺が参考になるかも
<?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はよくわからないので、コードがダサいかもしれません。
あしからず