don't stop believing

Web 서버 기본 구성 3 (API 서버에 파일 전송) 본문

Swift/Perfect

Web 서버 기본 구성 3 (API 서버에 파일 전송)

Tongchun 2018. 6. 24. 01:55

이어서 이번에는 파일을 API 서버에 전달해 보겠습니다.

macaron API에서 직원정보를 등록할 때 사진을 올릴 수 있게 만들었습니다.

post man을 이용해 파일을 올리때는 아래와 같습니다.


먼저 login을하고 accesstoken을 받습니다.


header에 AccessToken을 Key로하고 리턴받은 accesstoken을 넣습니다.

그리고 Body 데이터의 타입을 form-data로 선택하고 image에 데이터 타입으로 사진이 있는 경로를 넣고, id로 로그인한 id를 넣습니다.

Send를 클릭해 데이터를 보내면 저장된 이미지의 경로가 리턴됩니다.


macaron API 서버가 계속 수정되고 있어 portrait으로 받은 경로는 아래와 같이 변경해 볼 수 있습니다.

http://52.79.160.182:10260/v1/crew/portrait/tongchun_1529771272.jpg

이제 CURLRequest로 구현해 봅시다.

먼저 알아야 할 것이 post method는 raw 데이터인 string 형태와 html의 form 테그와 같은 form-data 형태, 그리고 바이너리 (파일) 데이터를 보낼 수 있는 형태 등 여러가지 타입으로 보낼 수 있습니다. 앞서 postman으로 보냈던 것과 같이 form parameter로 text인 id와 이미지(바이너리) 데이터인 image를 보내겠습니다.


request.swift를 열고 NgleRequest 클래스 안에 아래와 같이 작성합니다.

/// post field를 이용한 파일 전송
func sendFileByPostFields(_ uri: String, _ params: [String], _ header: [String: String], _ bodyParam: [String: String]) -> [String: Any] {

    var jsonDic = [String: Any]()
    var url: String = "http://\(self.host):\(self.port)\(uri)"

    if params.count > 0 {
        url.append("?")
        url.append(params.joined(separator: "&"))
    }

    // accessToken을 보내기 위한 custom Header
    let headerAccessToken = CURLRequest.Header.Name.custom(name: "AccessToken")
    let tokenValue: String = header["AccessToken"] ?? ""

    let testImagePath: String = bodyParam["image"] ?? ""
    let testId: String = bodyParam["id"] ?? ""

    do {
        let response = try CURLRequest(url, .failOnError,
                                       .addHeader(headerAccessToken, tokenValue),
                                       .postField(.init(name: "image", filePath: testImagePath, mimeType: "multipart/form-data")),
                                       .postField(.init(name: "id", value: testId))).perform()

        jsonDic = response.bodyJSON
    } catch {
        print("Fatal error \(error)")
    }

    return jsonDic
}

AccessToken을 보낼 header를 추가했고, postField를 이용해 image 와 id를 보내게 됩니다. 이때 이미지가 포함된 postField에는 mineType을 "multipart/form-data"로 지정해야 합니다.


이제 hander를 작성합니다.

handler.swift 파일을 열고 Handler 클래스 안에 아래와 같이 작성합니다.

/// post method 동기처리를 이용 (이미지 전송 예: sendFileByPostFields)
func callSendImageByPostSync(request: HTTPRequest, response: HTTPResponse) {
    var values = MustacheEvaluationContext.MapType()
    let nGle = NgleRequest(host: "52.79.160.182", port: 10260)

    let formParams: [String: String] = ["id": "tongchun", "image": "/Users/tongchunkim/Downloads/BLACKPINK17.jpg"]
    let accessTokenDic: [String: String] = ["AccessToken": "8F3C1222-C7D9-48B0-9344-8F2FCB59FF1E"]

    let jsonDic = nGle.sendFileByPostFields("/v1/crew/portrait", [], accessTokenDic, formParams)

    let crewData = jsonDic["data"] ?? ["":""]
    values["info"] = crewData

    let mustachHandler = MustacheHelper(values: values)
    let webPath = request.documentRoot + "/uploadresult.mustache"
    mustacheRequest(request: request, response: response, handler: mustachHandler, templatePath: webPath)
}

보내려는 formParams 데이터와 accessToken은 임의로 지정했습니다. 실제 Web 서버를 구현할 경우 client(브라우저)에서 데이터를 받아다 넘겨주면 됩니다.

저장하려는 이미지는 둘째놈이 좋아하는 BlackPink입니다.


mustache 파일은 아래와 같이 작성합니다.

uploadresult.mustache

<html> <header> <title>nGle Image Upload Result</title> </header> <body> <h1>nGle Image Upload Result</h1> {{#info}} <li>ID: {{id}}</li> <li>Name: {{name}}</li> <li>portrait: {{portrait}}</li> {{/info}} </body> </html>


이제 coltroller.swift에 Route를 추가해 줍니다.

Route(method: .get, uri: "/crew/portrait", handler: sample.callSendImageByPostSync)


실행하면 아래와 같이 html 화면이 출력됩니다.

앞서 얘기한것 같이 macaron API에서 이미지를 보는 uri가 변경되었습니다.

파일명을 가지고 macaron API에서 이미지를 확인하면 아래와 같습니다.


여기까지 CURLRequest를 이용한 이미지 업로드였습니다.


Comments