Swift4でAlamofire4を使ってMultipartで画像をサーバへアップロードする

Swift4でAlamofire4を使い、画像をテキストのフォームデータと混ぜたマルチパートでサーバへアップロードしたときのメモ書き。

```swift:HttpRequestSample.swift
import Alamofire

public class HttpRequestSample {

    // 画像付きのマルチパートでアップロード
    public func uploadMultipartFromData(parameters: [[String: Any]]) {
        let url = "https://example.com/api/hoge"
        let urlRequest = URL(string: url)!
        let headers: HTTPHeaders = [
            "Authorization": "Bearer QWxhZGRpbjpvcGVuIHNlc2FtZQ==",
            "Accept": "application/json"
        ];

        Alamofire.upload(
            multipartFormData: { (multipartFormData) in
                for element in parameters {
                    self.appendMultipartFormData(multipartFormData: multipartFormData, element: element)
                }
            },
            to: urlRequest,
            headers: headers,
            encodingCompletion: { encodingResult in
                // file をエンコードした後のコールバック
                switch encodingResult {
                case .success(let upload, _, _):
                    self.uploaldMultipartProcess(upload: upload, completeNotificationName: .uploadRequestComplete);
                case .failure(let encodingError):
                    print(encodingError)
                }
            }
        )
    }

    // マルチパートのフォームデータをmultipartFormDataに追加
    func appendMultipartFormData(multipartFormData: MultipartFormData, element: [String: Any]) {
        switch element["value"] {
        case let image as UIImage:
            var imageData: Data
            var mimeType: String
            if element["extension"] as! String == "jpg" {
                print(element["extension"] as! String)
                imageData = UIImageJPEGRepresentation(image, 1.0)!
                mimeType = "jpeg"
            } else {
                imageData = UIImagePNGRepresentation(image)!
                mimeType = "png"
            }
            multipartFormData.append(
                imageData,
                withName: element["key"] as! String,
                fileName: element["name"] as! String,
                mimeType: mimeType
            )
        default:
            let value = element["value"] as! String
            multipartFormData.append((value.data(using: .utf8))!, withName: element["key"] as! String)
            break
        }
    }

    // 画像エンコード完了後のアップロード処理
    func uploaldMultipartProcess(upload: UploadRequest, completeNotificationName: NSNotification.Name) {
        upload
            .uploadProgress(closure: { (progress) in
                print("Upload Progress: \(progress.fractionCompleted)")
            })
            .validate(statusCode: 200..<300)
            .validate(contentType: ["application/json"])
            .responseJSON { (response: DataResponse<Any>) in
                let statusCode = response.response?.statusCode
                print("Success: \(response.result.isSuccess)")
                print("Status code: \(String(describing: statusCode))")
        }
    }

    // 画像アップロード用のパラメータを生成
    public func generateUploadParameters(img: UIImage, fileExtension: String) -> [[String: Any]] {
        let parameters: [[String: Any]] = [
            ["key": "name", "value": "hoge"],
            ["key": "file", "value": img, "extension": fileExtension],
        ]
        return parameters
    }

}
```

```swift:呼び出し側
let parameters = HttpRequestSample.generateUploadParameters(img: image, fileExtension: "jpg")
let httpRequest = HttpRequest()
httpRequest.uploadMultipartFromData(
    parameters: parameters,
    requestPath: "media",
    completeNotificationName: .uploadRequestComplete
)
```