SwiftでイメージをPOSTした
POSTできました。
これはなに
Swiftにて、UIImageをサーバにPOSTしたかったときに若干詰まったので報告をしておきます。
なお、HTTPリクエストを送るのには
を使用しています。神ライブラリだ
やりたかったこと
Netの問題点
上記の要求に対して、
- 画像をアップロードするのには upload() を使う
- upload() は進捗率を返し、サーバのレスポンスを受け取らない
- POST() はサーバのレスポンスを受け取るが、画像はアップロードできない
とう状況になっていました。二律背反!
そもそも、自分でNSURLConnectionでリクエストしたらいいんじゃないの
もちろん、自前でリクエストを送るのは何度もやっていて、 何度もやっているからこそライブラリに頼りたい。エラーハンドリングめんどくさいしね。
自前で書いたことない人はドキュメントなりブログなりをググってちゃんと調べましょう。 はまったときに死にます。
解決方法(うそ)
- upload()を使って、パラメータは別で取得すればよい
クライアントをいじらず、サーバをいじる方法です。
そう実装できたらスマートだったんですが、初めて使う言語・フレームワークだったためよくわからず却下。
解決方法(本当)
- POST()を使い、ヘッダを自分で設定する
コードを見た方が早い
class func sendImage(image: UIImage, to: String, success: Success, failure: Failure) { let path = "/post" let imageData = NetData(pngImage: image, filename: "test") let myName = User.getMe()!.name let params = ["data": imageData, "from": myName, "to": to] let boundary = "NET-UPLOAD-boundary-\(arc4random())-\(arc4random())" let paramsData = NetHelper.dataFromParamsWithBoundary(params, boundary: boundary) let header = ["Content-Length": "\(paramsData.length)", "Content-Type": "multipart/form-data; boundary=\(boundary)"] let net = Net(baseUrlString: "http://localhost", header: header) net.POST(path, params: params, successHandler: success, failureHandler: failure) }
上の4行はpathとparameterを設定しています。
下5行はヘッダを設定してリクエストを送っています。
要は
- imageDataとparamsを送る時は、 Content-Type、Content-Length を設定すればよい
なんというか、NSURLConnection で実装するときは当たり前でしょ?
せっかくコードを読んだのでbondaryのStringと、パラメータをNSDataに変換するところはNetから拝借しました。
ハマったとこ
- UIImageをNSDataに変換する部分
上のコードの let imageData =
のところですね。
最初は普通に
let imageData = UIImagePNGRepresentation(image)
としていたのですが、どうもサーバに送られていないっぽい。
Net のコードを読むと、parameterにImageが含まれるかどうかを if value is NetData で判定していることがわかりました。
なので、
let imageData = NetData(pngImage: image, filename: "適当なファイル名")
としておわり。
イニシャライザの引数としては、pngImage, jpegImage があった
ライブラリのコードを読め