今回は、ファイルのアップロードを行うのでASIFormDataRequestクラスを使用することにする。
ついでにプログレスバーで進捗状況も確認できるようにしてみる。
まずはダウンロード。
ASIHTTPRequest Documentation - All-Seeing Interactive
http://allseeing-i.com/ASIHTTPRequest/
latest version のものをダウンロードする。
次に、ダウンロードしたファイルの中にある、Classesの中身全部とExternalの中にあるReachabilityを自分のプロジェクトに取り込む。
Reachability は一見不要そうだけど、追加しないとASIHTTPRequestクラス群が使えない。
それと、ASIHTTPRequestクラス群を使用するにあたり必要な、下記のフレームワークとライブラリも追加する。追加しないとASIHTTPRequestクラス群が使えないので注意。
iOS4に含まれているので普通に追加すればOK.
追加後のイメージはこんな感じ。
下準備は整ったので、次はコードを書いて実装していく。
実装する機能は以下の二点。
アプリ起動時に最初に呼び出される FirstViewController に処理を書いた。
下記、コード。
主要部分だけを説明していく。赤字の部分がポイント箇所。
◎FirstViewController.h
#import <UIKit/UIKit.h>
#import "ASIFormDataRequest.h"
#import "ASINetworkQueue.h"
@interface FirstViewController : UIViewController {
UIProgressView *pb; // プログレスバー
UISwitch *sw; // スイッチ
}
@end
ASINetworkQueue.h はプログレスバーで進捗状況を確認するのに使う。
進捗状況を確認しないのであれば、importしないでOK.
◎FirstViewController.m
#import "FirstViewController.h"
@implementation FirstViewController
- (void)dealloc
{
[pb release];
[sw release];
[super dealloc];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
// ボタン表示
[self uplaodFileButton];
// プログレスバー表示
[self progressBar];
// ラベルを表示
[self label];
// スイッチ表示
[self switchPb];
}
//--------------------------------------------------
// ファイルアップロードボタン
//--------------------------------------------------
// ボタンを追加
- (void)uplaodFileButton
{
UIButton *bt = [UIButton buttonWithType:UIButtonTypeRoundedRect];
bt.frame = CGRectMake(60, 150, 200, 40);
[bt setTitle:@"ファイルアップロード" forState:UIControlStateNormal];
[bt addTarget:self action:@selector(uplaodDataButtonAction:)forControlEvents:UIControlEventTouchDown];
[self.view addSubview:bt];
}
// ボタンアクション
- (void)uplaodDataButtonAction:(UIButton*)button
{
// アップロード
[self uploadStart];
}
//--------------------------------------------------
// プログレスバー
//--------------------------------------------------
// プログレスバーを追加
- (void)progressBar
{
pb = [[[UIProgressView alloc]
initWithProgressViewStyle:UIProgressViewStyleDefault] autorelease];
pb.frame = CGRectMake(60, 20, 200, 10);
pb.progress = 0.0;
[self.view addSubview:pb];
}
//--------------------------------------------------
// ラベル
//--------------------------------------------------
// ラベルを追加
- (void)label
{
UILabel *label = [[UILabel alloc] init];
label.frame = CGRectMake(15, 265, 200, 50);
label.textColor = [UIColor blackColor];
label.font = [UIFont systemFontOfSize:[UIFont systemFontSize]];
label.textAlignment = UITextAlignmentLeft;
label.text = @"プログレスバーを使用する";
[self.view addSubview:label];
}
//--------------------------------------------------
// スイッチ
//--------------------------------------------------
// スイッチを追加
- (void)switchPb
{
sw = [[[UISwitch alloc] init] autorelease];
sw.center = CGPointMake(250, 290);
sw.on = NO;
[self.view addSubview:sw];
}
//--------------------------------------------------
// アップロード処理
//--------------------------------------------------
- (void)uploadStart {
NSURL *url = [NSURL URLWithString:@"http://localhost/test/uploadsample.php"];
ASIFormDataRequest *request = [[[ASIFormDataRequest alloc] initWithURL:url] autorelease];
[request setPostValue:@"hoge" forKey:@"file_name"]; // ファイル名(仮名:hoge)
[request setPostValue:@"jpg" forKey:@"extension"]; // 拡張子
// データをセット
NSString *path = [[NSBundle mainBundle] pathForResource:@"A5B8A1BCA5D7A3B1" ofType:@"jpg"];
NSData *image = [NSData dataWithContentsOfFile:path];
[request setData:image forKey:@"upfile"];
[request setTimeOutSeconds:120];
[request setDelegate:self];
[request setDidFinishSelector:@selector(postSucceeded:)];
[request setDidFailSelector:@selector(postFailed:)];
[request setDefaultResponseEncoding:NSUTF8StringEncoding];
if (sw.on == 0) {
// プログレスバーを使用せずに非同期通信する場合に使用
[request startAsynchronous];
NSLog(@"プログレスバー未使用");
} else {
// プログレスバーを使用する
ASINetworkQueue *networkQueue = [[ASINetworkQueue alloc] init];
[networkQueue setUploadProgressDelegate:pb];
[networkQueue setShowAccurateProgress:YES];
[networkQueue addOperation:request]; // 非同期通信
[networkQueue go];
NSLog(@"プログレスバー使用");
}
}
- (void)postSucceeded:(ASIFormDataRequest *)request
{
NSString *resString = [request responseString];
NSLog(@"%@", resString);
}
- (void)postFailed:(ASIFormDataRequest *)request
{
NSString *resString = [request responseString];
NSLog(@"%@", resString);
}
@end
[request startAsynchronous]; のところは、 [request startSynchronous]; にすると同期通信になるはず。
ついでにサーバー側の処理(PHP)のコードも。
◎uploadsample.php
<?php
$file_name = $_POST["file_name"];
$extension = $_POST["extension"];
if (is_uploaded_file($_FILES["upfile"]["tmp_name"])) {
if (move_uploaded_file($_FILES["upfile"]["tmp_name"], "./" . $file_name . "." . $extension)) {
echo $file_name . "." . $extension . "をアップロードしました。";
} else {
echo "ファイルをアップロードできません。";
}
} else {
echo "ファイルが選択されていません。";
}
?>
以上。
ちゃんとファイルがアップロードできるか確認。
アプリを起動をして、「ファイルアップロード」ボタンを押下。
うーん・・・目に見えて変化がないから分からないけど、実際にはちゃんとファイルがアップロードされてるはず。
Terminalで確認してみる。
あった!!hoge.jpg!
データ内容にも問題がないか確認。
うん、OK.
最後に、ファイルをアップロードするっていう処理自体は同じだけど、プログレスバーを使用してアップロード状況も確認してみる。
こっちのほうが目に見えて分かりやすい。
もちろんアップロードされた画像も問題なく表示できました。
ちなみに、FirstViewController.m の
// データをセット
NSString *path = [[NSBundle mainBundle] pathForResource:@"A5B8A1BCA5D7A3B1" ofType:@"jpg"];
NSData *image = [NSData dataWithContentsOfFile:path];
[request setData:image forKey:@"upfile"];
の部分を省けば、ただのVALUE値をPOSTするだけになる。
文字列だけを送信して、サーバ側で何か処理をさせたいとき(DB処理とか)にも使える。
次回はBASIC認証機能を説明しようかな。
----------
サンプルソース:https://github.com/tetsuco/SampleASIFormDataRequest_with_srv