[iOS/Swift] multipart/form-data 형식으로 서버에 이미지 전송하기

Nakyung Lee·2023년 7월 5일
1

iOS

목록 보기
3/14

회원가입을 할 때 사용자가 프로필 이미지로 지정한 사진을 서버에 전송해 주어야 하는데 검색해 보니 이를 위해서는 form-data 형식으로 전달해 주어야 한다고 한다.

multipart/form-data?

✍️ multipart/form-data는 파일 업로드가 있는 양식 요소에 사용되는 enctype 속성의 값 중 하나이고, multipart는 폼 데이터가 여러 부분으로 나뉘어 서버로 전송되는 것을 의미한다.

Alamofire 라이브러리에서는 이 형식을 제공해 주고 있으며, 이미지를 데이터로 변환하여 전송하는 것이다.

1. Header 작성

let header: HTTPHeaders = [ "Content-Type" : "multipart/form-data" ]

2. 기본 request body로 보낼 parameter 작성

let params: Parameters = [
    "user_id": userId,
    "pwd": pwd,
    "name": name,
    "age": age
]

3. request body 추가 후 이미지 추가해 주기

AF.upload(multipartFormData: { MultipartFormData in
    for (key, value) in params {
        MultipartFormData.append("\(value)".data(using: .utf8)!, withName: key)
    }
        // 이미지 추가
        if let image = imgData?.pngData() {
           MultipartFormData.append(image, withName: "image", fileName: "\(name).jpg", mimeType: "image/jpg")
        } 
    }, to: signUpURL, usingThreshold: UInt64.init(), method: .post, headers: header).responseData { response in
        switch response.result {
        	case .success:
            	guard let statusCode = response.response?.statusCode else { return }
            	guard let data = response.value else { return }
            	completion(judgeSignUpData(status: statusCode, data: data))
            case .failure(let err):
            	print(err)
                completion(.networkFail)
        }
    }

💻 전체 코드

func signUp(userId: String, pwd: String, name: String, age: String, imgData: Data) {
	// 헤더 작성 (Content-type 지정)
    let header: HTTPHeaders = [ "Content-Type" : "multipart/form-data" ]
        
    // 파라미터
    let params: Parameters = [
        "user_id": userId,
        "pwd": pwd,
        "name": name,
        "age": age
    ]
        
    AF.upload(multipartFormData: { MultipartFormData in
        for (key, value) in params {
        MultipartFormData.append("\(value)".data(using: .utf8)!, withName: key)
    }
        // 이미지 추가 (이미지 없을 경우 고려)
        if let image = imgData?.pngData() {
            MultipartFormData.append(image, withName: "image", fileName: "\(name).jpg", mimeType: "image/jpg")
        } 
    }, to: signUpURL, usingThreshold: UInt64.init(), method: .post, headers: header).responseData { response in
        switch response.result {
        case .success:
           	guard let statusCode = response.response?.statusCode else { return }
            guard let data = response.value else { return }
            completion(judgeSignUpData(status: statusCode, data: data))
        case .failure(let err):
            print(err)
            completion(.networkFail)
        }
    }
}

private func judgeSignUpData(status: Int, data: Data) -> NetworkResult<Any> {
        // 통신을 통해 전달받은 데이터를 decode
        switch status {
        case 200:
            let decoder = JSONDecoder()
            guard let decodedData = try? decoder.decode(TokenModel.self, from: data) else { return .pathErr }
            print("회원가입 :: Success")
            return .success(decodedData)
        case 400..<500:
            return .requestErr
        case 500:
            return .serverErr
        default:
            return .networkFail
        }
    }

form-data 형식으로 보내는 것은 처음이라 걱정했는데, 하다보니까 그냥 post, get 형식과 비슷한 것 같았다.

서버에 이미지 보내기 성공 👏

profile
앱 개발자를 꿈꾸는 ✨

0개의 댓글