multipart/form-data는 HTTP POST 요청에서 특정 데이터 형식을 나타내는 MIME 유형 중 하나입니다. 이 형식은 파일 업로드와 같은 바이너리 데이터 전송에 사용됩니다. Swift에서 multipart/form-data를 보내기 위해서는 URLSession을 사용해야 합니다. 이를 위해 URLSession에서 POST 요청을 생성하고, HTTPBody에 데이터를 추가해야 합니다. 이 과정에서 boundary를 생성하고, 각각의 데이터를 boundary로 나누어야 합니다. 아래는 multipart/form-data를 보내는 예시코드입니다. 이 코드는 파일을 업로드하는 예시이며. 파일 외에 다른 데이터를 추가하려면 HTTPBody를 수정해야합니다.

func uploadFile() {
    let url = URL(string: "<https://example.com/upload>")
    var request = URLRequest(url: url!)
    request.httpMethod = "POST"
    
    let boundary = "Boundary-\\(UUID().uuidString)"
    request.setValue("multipart/form-data; boundary=\\(boundary)", forHTTPHeaderField: "Content-Type")
    
    let image = UIImage(named: "example.jpg")
    let imageData = image?.jpegData(compressionQuality: 1)
    
    var data = Data()
    data.append("--\\(boundary)\\r\\n".data(using: .utf8)!)
    data.append("Content-Disposition: form-data; name=\\"file\\"; filename=\\"example.jpg\\"\\r\\n".data(using: .utf8)!)
    data.append("Content-Type: image/jpeg\\r\\n\\r\\n".data(using: .utf8)!)
    data.append(imageData!)
    data.append("\\r\\n".data(using: .utf8)!)
    data.append("--\\(boundary)--\\r\\n".data(using: .utf8)!)
    
    request.httpBody = data
    
    let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
        // Handle response
    }
    
    task.resume()
}

이 코드에서 HTTPBody에 파일 데이터를 추가하기 위해 Data()를 사용합니다. boundary와 데이터를 나누기 위해 "--\\(boundary)--\\r\\n"과 같은 문자열을 사용합니다. 파일 데이터는 "Content-Disposition: form-data; name=\\"file\\"; filename=\\"example.jpg\\"\\r\\n"과 같은 형식으로 HTTPBody에 추가됩니다. multipart/form-data를 사용할 때는 주의할 점이 있습니다. 파일이나 바이너리 데이터를 전송하는 경우에는 데이터 크기가 크기때문에 HTTPBody에 직접 추가하지 않고, 파일을 분할해서 전송하는 방식을 사용하는 것이 좋습니다. 또한 데이터 전송에 대한 보안문제가 있을 수 있으므로 HTTPS를 사용하는것이 좋습니다.

// 요청 URL 및 파라미터 설정
let urlString = "<https://example.com/upload>"
let parameters = ["name": "John", "age": "30"]

// 요청 객체 생성
var request = URLRequest(url: URL(string: urlString)!)
request.httpMethod = "POST"

// boundary 생성
let boundary = "Boundary-\\(UUID().uuidString)"
let contentType = "multipart/form-data; boundary=\\(boundary)"
request.setValue(contentType, forHTTPHeaderField: "Content-Type")

// body 생성
var body = Data()

for (key, value) in parameters {
    // parameter 구분자 생성
    body.append("--\\(boundary)\\r\\n".data(using: .utf8)!)
    body.append("Content-Disposition: form-data; name=\\"\\(key)\\"\\r\\n\\r\\n".data(using: .utf8)!)
    body.append("\\(value)\\r\\n".data(using: .utf8)!)
}

// 이미지 파일 추가
if let image = UIImage(named: "example.jpg"), let imageData = image.jpegData(compressionQuality: 1.0) {
    body.append("--\\(boundary)\\r\\n".data(using: .utf8)!)
    body.append("Content-Disposition: form-data; name=\\"file\\"; filename=\\"example.jpg\\"\\r\\n".data(using: .utf8)!)
    body.append("Content-Type: image/jpeg\\r\\n\\r\\n".data(using: .utf8)!)
    body.append(imageData)
    body.append("\\r\\n".data(using: .utf8)!)
}

// body 마무리
body.append("--\\(boundary)--\\r\\n".data(using: .utf8)!)
request.httpBody = body

// URLSession을 사용하여 요청 보내기
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
    // 요청 완료 후 처리할 내용
    if let error = error {
        print("Error: \\(error)")
        return
    }
    
    if let data = data {
        let responseString = String(data: data, encoding: .utf8)
        print("Response: \\(responseString)")
    }
}
task.resume()

위 예제 코드에서는 URLRequest 객체를 생성하고 httpMethodPOST로 설정합니다. 그리고 Content-Typemultipart/form-data로 설정합니다. 그리고 각각의 파라미터와 이미지 파일을 body에 추가하여 요청을 완성합니다.

이 코드는 단순히 예제일 뿐이며, 요청 URL 및 파라미터, 파일명 등은 실제 사용에 맞게 변경해야 합니다. 또한, boundary를 고유한 값을 사용하여 생성해야 합니다.

참고

https://nsios.tistory.com/39

https://lena-chamna.netlify.app/post/uploading_array_of_images_using_multipart_form-data_in_swift/


파일 업로드 구현할때 HTTP 메시지는 Content-Type속성이 Multipart/form-data로 지정된다.그리고 이형식에 따라서 메시지를 인코딩하여 전송한다. 서버는 이를 처리하기 위해 각 파트별로 분리하여 개별 파일의 정보를 얻는것이다. 그렇기 때문에 앱에서 구현하기 위해서 multipart/form-data 의 형식을 따른다.

http(Request 와 response)는 아래의 네개로 나뉜다.

Untitled