LoginSignup
2
3

More than 5 years have passed since last update.

Swift で外部ライブラリを使わずに画像を Post する。

Posted at

外部のライブラリに依存しないで画像を Post する方法を見かけなかったので、以前 Objective-C で書いていたのを元に書いてみた。

文字列で投稿用の NSData を組み立てる為、ちょっと拡張しておく。

ちょっとした拡張
extension NSMutableData {
    func appendString(string: String, encoding: UInt = NSASCIIStringEncoding) {
        guard let data = string.dataUsingEncoding(encoding) else {
            // お好きなように
            return
        }
        appendData(data)
    }
}

こっちが送信用。エラー処理はプロジェクトにあわせて上手いことやってください。画像以外に文字列も送信したい場合は params に辞書形式で渡してください。ヘッダにトークンなんかの値をもたせたいときは NSMutableURLRequest::setValue() でヘッダに値をセット出来ます。

送信用

class ImageUploader {
    func exec(image: UIImage, params: [String: String]?, urlString: String, httpMethod: String = "POST", completeHandler: (status: Bool) -> Void) {
        guard let url = NSURL(string: urlString) else {
            completeHandler(status: false)
            return
        }
        guard let imageData = UIImagePNGRepresentation(image) else {
            completeHandler(status: false)
            return
        }

        let request = NSMutableURLRequest(URL: url)
        request.HTTPMethod = httpMethod

        let boundary = "Boundary-\(NSUUID().UUIDString)"

        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
        request.HTTPBody = createBody(params, fileParamName: "image", imageData: imageData, boundary: boundary)

        let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
            data, response, error in
            if let error = error {
                completeHandler(status: false)
                return
            }
            guard let data = data else {
                completeHandler(status: false)
                return
            }

            let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
            dispatch_async(dispatch_get_main_queue(), {
                completeHandler(status: true)
            })
        }
        task.resume()
    }

    // fileParamName は画像のパラメータ名
    private func createBody(params: [String: String]?, fileParamName: String, imageData: NSData, boundary: String) -> NSData {
        let body = NSMutableData()
        if let params = params {
            for (key, value) in params {
                body.appendString("--\(boundary)\r\n")
                body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
                body.appendString(value, encoding: NSUTF8StringEncoding)
                body.appendString("\r\n")
            }
        }
        let filename = "test.png"
        let mimetype = "image/png"
        body.appendString("--\(boundary)\r\n")
        body.appendString("Content-Disposition: form-data; name=\"\(fileParamName)\"; filename=\"\(filename)\"\r\n")
        body.appendString("Content-Type: \(mimetype)\r\n\r\n")
        body.appendData(imageData)
        body.appendString("\r\n")
        body.appendString("--\(boundary)--\r\n")
        return body
    }
}

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3