[Swift] multipart/form-data (with Alamofire)

김혜수·2021년 9월 12일

내가 보내야 하는 내용

title (String)
taken (Boolean)
date (String)
category ([String])
record (String)
friendIdx ([String])
photo (file 배열)

Code

Service 코드

import Foundation
import Alamofire

struct KeepinAddService {
    
    static let shared = KeepinAddService()
    
    func postKeepin(title: String,
                    taken: Bool,
                    date: String,
                    category: [String],
                    record: String?,
                    friendIdx: [String],
                    imageData: [UIImage],
                    completion: @escaping (NetworkResult<Any>) -> Void) {

        
        let parameters: [String: Any] = [
            "title": title,
            "taken": taken,
            "date": date,
            "category": category,
            "record": record ?? "",
            "friendIdx": friendIdx
        ]
        let url = "\(URL 주소 적어주기)"
        let header : HTTPHeaders = [
            "Content-Type" : "multipart/form-data",
            "jwt" : "\(해당 토큰 넣어주기)" ]
        
        
        //multipart 업로드
        AF.upload(multipartFormData: { (multipart) in
            
            /// imageData 배열을 돌면서 이미지 추가해주기
            for image in imageData {
                if let image = image.jpegData(compressionQuality: 1) {
                    multipart.append(image, withName: "photo", fileName: "\(imageData).jpg", mimeType: "image/jpeg") // jpeg 파일로 전송
                }
            }
            
            for (key, value) in parameters {
                
                /// category와 friendIdx는 배열로 들어오기 때문에 그만큼 append를 더 해줘야 한다. (그냥 배열로 보내면 잘못보내지더라구요!)
                if ((key == "category") || (key == "friendIdx")) {
                    
                    for idx in value as! [String] {
                        multipart.append("\(idx)".data(using: .utf8, allowLossyConversion: false)!, withName: "\(key)")
                    }
                    
                }
                else {
                    multipart.append("\(value)".data(using: .utf8, allowLossyConversion: false)!, withName: "\(key)")
                }
            }
        }, to: url 
        ,method: .post  
        ,headers: header).responseJSON(completionHandler: { (response) in 
            print(response)
            
            if let err = response.error{
                print(err)
                return
            }
            print("success") 
        })
    }
}

VC에서의 서버연결 코드

KeepinAddService.shared.postKeepin(title: nameTextField.text!,
                                           taken: take,
                                           date: dateTextfield.text!.replacingOccurrences(of: ".", with: "-"),
                                           category: categoryList,
                                           record: memoTextView.text!,
                                           friendIdx: friendIdxList,
                                           imageData: imgList) { result in
            
            switch result {
            case .success(let msg):
                print("success", msg)
            case .requestErr(let msg):
                print("requestERR", msg)
            case .pathErr:
                print("pathERR")
            case .serverErr:
                print("serverERR")
            case .networkFail:
                print("networkFail")
            }
        }

알게된, 헷갈렸던 내용 메모

  • multipart/form-data 형태로 파일을 보낼때는 AF.upload 메서드를 사용한다.
  • postman에서 실행할 때 [body] - [form-data]에서 한다.
    • 이때 배열은 보내지지 않기에 key 값 하나당 하나만 보내야 한다.
    • 만약 둘 이상의 요소를 보내야 한다면 같은 key 여러개 생성해서 보내면 된다.

      요런식으로!
  • 하지만 swift 에서는 Dictionary 형태에서 동일한 key 값 2개이상을 생성해주지 못한다. 따라서 반복문을 사용해서 append를 여러번 해주면 된다.!
profile
iOS를 좋아하는 사람

0개의 댓글