Alamofire+Multipart

pcsoyeon·2021년 11월 12일
0

Open Library

목록 보기
3/3

Multipart?

Alamofire로 이미지 통신을 한다면?
-> multipart는 alamofire에서 제공해주는 기능으로 이미지를 data로 전환해서 전송하는 방식을 말한다.
(multipart/form-data는 파일 업로드가 있는 양식 요소에 사용되는 enctype 속성 중 하나이고 multipart는 form-data가 여러 부분으로 나뉘어서 서버로 전송되는 것을 말한다.)

해당 값을 언제 사용하는지는 서버의 API문서를 살펴볼 때 알 수 있다.
만약 Request Header에서 Content-Type이 multipart/form-data로 되어 있다면 해당 속성 값을 request 배열 영역에 잘 입력해야 한다.

그리고 Request Body 부분에 이미지를 제외하고 업로드를 할 데이터가 있다면 multipart를 이용해서 데이터를 분리하여 업로드를 해야 한다.

프로젝트 파일에 적용해보자

기존 Alamofire의 통신 방식과 비슷하다. Request Header와 Request Body를 API 문서를 기반으로 작성하면 된다. (key-value 형식으로)

let URL = APIConstants.baseURL

URL을 작성하고

let token = UserDefaultStorage.accessToken
let header : HTTPHeaders = [
	"Content-Type" : "multipart/form-data",
	"token" : token
]

API Request Header를 작성한다. 이미지를 포함한 여러 데이터를 보내 서버와 통신하는 multipart/form-data이므로 위와 같이 작성하면 된다.

let parameters: [String : Any] = [
            "sampleContent": content,
            "sampleIndex": index,
]

앞서 말한 것처럼 key-value 배열 형식으로 Request Body를 작성한다.
여기서 포인트는 실제로 서버 API에서 필요한 body는 sampleImage(image 형식), sampleContent(strign), sampleIndex(int) 이지만 sampleImage의 경우 다른 string이나 int형식의 요청 바디와 다르게 multipart를 통해 따로 data로 변환시켜 데이터를 전송시킬 것이므로 따로 parameters 배열에 넣지 않아도 된다.

이후로 alamofire에서 제공하는 upload를 통해 데이터를 전송한다.
upload 과정은 다음과 같다.

  1. 기본 request body를 추가한다.
for (key, value) in parameters {
    multipartFormData.append("\(value)".data(using: .utf8)!, withName: key)
}

request body에 있는 key-value 값을 for믄을 통해서 각각 multipartFromData에 추가하여 전송한다.

  1. 이미지를 추가한다.
if let image = imageData?.pngData() {
    multipartFormData.append(image, withName: "sampleImage", fileName: "\(image).png", mimeType: "image/png")
}

image의 경우 nil값을 고려해서 if let 을 통해 전송하고 그 뒤에는 어떤 데이터를 어떤 이름과 형식으로 전송할 것인지 작성한다.


여기서 각 파라미터가 의미하는 것은 다음과 같다.
✔️ withName - key 값
✔️ fileName - 서버에 업로드할 파일 이름
✔️ mimeType - 파일 형식

데이터를 보내는 코드를 다 작성한 후에 데이터를 전송할 url과 통신 방법, 헤더를 작성 후 응답을 받아오면 된다.

, to: URL, usingThreshold: UInt64.init(), method: .post, headers: header).response { response in
            guard let statusCode = response.response?.statusCode,
                  statusCode == 200
            else { return }
            completion(.success(statusCode))
}

이후 해당 VC로 가서 기존의 alamofire 서버 통신과 같은 방법으로 위의 서비스를 불러와서 통신을 완료하면 된다.

func didTapUploadButton(_ sender: UIButton) {
AddActionEditService.shared.editActivity(imageData: buttonImage,
					content: activityTextView.text!,
					year: String(date[0]),
					month: String(date[1]),
					day: String(date[2]),
					index: characterIndex,activityIndex: 36) { result in
                    switch result {
                    	case .success(let msg):
                    	print("success", msg)
                    	self.dismiss(animated: true, completion: nil)
                        
                    	case .requestErr(let msg):
                    	print("requestERR", msg)
                        
                    	case .pathErr:
                    	print("pathERR")
                        
                    	case .serverErr:
                    	print("serverERR")
                        
                    	case .networkFail:
                    	print("networkFail")
                }
}
profile
Slowly But Surely

0개의 댓글