この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
こんばんは。モバイルアプリサービス部の平屋です。
以下の記事でNode.js + express + Multerでファイルアップロード API を作成する手順を紹介しました。
同じ機能を持つアプリを、Swift製WebフレームワークVaporを使用して作成してみましたので、その手順を紹介していきます。
検証環境
- macOS Sierra 10.12.3
- Xcode 8.2.1
- Homebrew 1.1.1
- swiftenv 1.2.1
- Swift Snapshot DEVELOPMENT-SNAPSHOT-2017-03-09-a
- Vapor Toolbox 1.0.5
環境構築
以下の記事と同じ手順でswiftenvとVapor Toolboxを使用して環境を構築しました。
Vaporで始めるサーバーサイドSwift 〜Mac上での環境構築からHello, World!まで〜 (swiftenv, Vapor Toolboxを使用)
環境が構築できたら、vaporコマンドを使用してサーバーサイドアプリのプロジェクトを作成します。
$ vapor new vapor-multipart-formdata-sample
main.swiftを修正
プロジェクトのSources/Appディレクトリ内のmain.swiftを修正して、POSTリクエストを受け付けられるようにします。
以下のように、13-26行目を追加します。
import Vapor
import Foundation
let drop = Droplet()
drop.get { req in
return try drop.view.make("welcome", [
"message": drop.localization[req.lang, "welcome", "title"]
])
}
// ここから
drop.post { req in
guard let field = req.formData?["file"] else {
return JSON(["result":"receive failure"])
}
do {
let dest = URL(fileURLWithPath: field.filename!)
try Data(field.part.body).write(to: dest)
} catch {
return JSON(["result":"save failure"])
}
return JSON(["result":"success"])
}
// ここまでを追加
drop.resource("posts", PostController())
drop.run()
14行目では、RequestオブジェクトのformData
プロパティからname
が"file"
のField構造体を取り出しています。Field構造体は、ファイル名やバイナリデータなどを持ちます。
19行目ではファイル名を取り出し、20行目では受け取ったデータをファイルとして保存しています。
動作確認
サーバーサイドアプリを実行
以下のコマンドを実行して、サーバーサイドアプリのビルドとサーバーの起動を行います。ポート8080でリクエストを受け付けるようになります。
$ vapor build
$ vapor run serve
iOS アプリからファイルをアップロードする
iOS アプリの場合、以下のような実装でファイルをアップロードできます。
iOS + Swift + Alamofire
func upload() {
let path = Bundle.main.path(forResource: "image", ofType: "png")
let fileURL = URL.init(fileURLWithPath: path!)
Alamofire.upload(
multipartFormData: { multipartFormData in
multipartFormData.append(fileURL, withName: "file")
},
to: "http://192.168.0.11:8080/",
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
debugPrint(response)
}
case .failure(let encodingError):
print(encodingError)
}
}
)
}
iOS + Objective-C + AFNetworking
- (void)upload
{
NSString *path = [[NSBundle mainBundle] pathForResource:@"image" ofType:@"png"];
NSURL *fileURL = [NSURL fileURLWithPath:path];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager POST:@"http://192.168.0.11:8080" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileURL:fileURL
name:@"file"
error:nil];
} progress:nil success:^(NSURLSessionTask *task, id responseObject) {
NSLog(@"success");
} failure:^(NSURLSessionTask *task, NSError *error) {
NSLog(@"error:%@", error.localizedDescription);
}];
}
動作結果
iOS アプリからアップロード操作を行い、サーバーサイドアプリのルートディレクトリにファイルがアップロードされることを確認できました。
さいごに
本記事ではSwift製WebフレームワークVaporを使用してファイルアップロード API を作成する手順を紹介しました。
以前作成したNode.js版のものと同じぐらい簡単に作れることがわかりました。
今回解説したサンプルアプリケーションは以下のリポジトリで公開しています。
参考資料
- Vapor
- Vapor Documentation
- vapor/multipart
- Vaporで始めるサーバーサイドSwift 〜Mac上での環境構築からHello, World!まで〜 (swiftenv, Vapor Toolboxを使用)
- Installation — swiftenv 1.1.0 documentation
- Swift.org - Download Swift
- Uploading files using Vapor - Stack Overflow
- xcode - Swift 3 How To Send A Multipart Post Request With Vapor - Stack Overflow
- vapor swift file upload - Stack Overflow
- リクエストとレスポンスの仕組み