file upload from iPhone to node server


iPhoneからnodeサーバにファイルをアップロードする方法。

## サーバサイド
今回はnodeでよく用いられるexpressフレームワークを使う。

* express 3.1.0
* node 0.8.18

特に他にモジュールは入れないで大丈夫。
app.jsは以下のようにする。変更してある箇所だけコメント追記。

```app.js
/**                                                                                                                                                                                 
 * Module dependencies.                                                                                                                                                             
 */

var express = require('express')
  , routes = require('./routes')
  , user = require('./routes/user')
  , http = require('http')
  , path = require('path');


var app = express();

app.configure(function(){
  app.set('port', process.env.PORT || 3001);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'ejs');
  app.use(express.favicon());
  app.use(express.logger('dev'));
  // uploadされたファイルのデフォルトディレクトリを決める。
  // アップロードされると基本的にここに入る
  app.use(express.bodyParser({uploadDir:'./uploads'}));
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(path.join(__dirname, 'public')));
});

app.configure('development', function(){
  app.use(express.errorHandler());
});


app.get('/', routes.index);
app.get('/users', user.list);
// postでファイルデータを受け取る。iPhoneからはここのURLを指定させておく
app.post('/file-upload', routes.fileUpload);

http.createServer(app).listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));
});
```

アップロード先のfile-uploadはこんな感じ。

```routes/index.js
/*                                                                                                                                                                                  
 * GET home page.                                                                                                                                                                   
 */

exports.index = function(req, res){
  res.render('index', { title: 'Express' });
};

exports.upload = function(req, res){
    console.log(req);
    res.render('upload', { title : 'Upload' });
};

// デバッグ用に出力してるだけ。req.filesにファイルの情報がいろいろはいってる。基本的にexpressがやってくれる。
exports.fileUpload = function(req, res){
    console.log(req.body);
    console.log(req.files);
    res.render('index', { title : 'Express' });
};

```


## クライアントサイド
iPhone側のコード。今回は[R9HTTPRequest](http://d.hatena.ne.jp/glass-_-onion/20120304/1330826940)というライブラリを使わせてもらった。簡単にかける。コードを参考にさせてもらったのは[ここ](http://rdeguchi.net/?p=1)

```upload.m
- (void)uploadFile{
    NSURL *uploadURL = [NSURL URLWithString:@"http://example.com/file-upload"];
    R9HTTPRequest *request = [[R9HTTPRequest alloc] initWithURL:uploadURL];
    [request setHTTPMethod:@"POST"];

	// 何かパラメータ付けたければこんな感じ
    [request addBody:@"upload" forKey:@"query_type"];

	// 動画ファイルをくっつける
    NSData *movieData = [NSData dataWithContentsOfFile:[outputFileURL path]];
    [request setData:movieData
        withFileName:@"uploadVideo.MOV"
      andContentType:@"MOV"
              forKey:@"key"];

	// レスポンスが返ってきた時のコールバックを設定    
    [request setCompletionHandler:^(NSHTTPURLResponse *responseHeader, NSString *responseString){
        NSLog(@"responseString: %@",responseString);
    }];
    
	// リクエスト送信
    [request startRequest];

}

```

これでexpress側のupload以下に入っている。ただ名前がランダムなものが設定されているので変更したければ変更する必要がある。