์ฌ์ด๋ ํ๋ก์ ํธ ์งํ ์ค ์ด๋ฏธ์ง๋ฅผ ์๋ฒ๋ก ์ ๋ก๋ ํด์ผํ๋ ํ์คํฌ๊ฐ ์์๋ค!
๊ธฐ์กด์ ๋ชจ๋ API๋ฅผ Alamofire๋ก ํต์ ํ๊ณ ์์๊ธฐ ๋๋ฌธ์ ์ด๋ฏธ์ง ํต์ ์ญ์ Alamofire๋ก ์งํํ๋ค.
๊ตฌํ์ ๋ค ํด๋์๋๋ฐ, ๋ ์ฐพ์๋ณด๋ฉด์ ์ ์ฉํ ๋ด์ฉ์ด ์๋ ์์๋ณด๊ธฐ ์ํด, ๋์ค์ ๋ค์ ๋ณด๊ธฐ ์ํด ๊ธฐ๋กํ๋ ค ํ๋ค. ๐
๊ณต์ ๋ฌธ์๋ฅผ ๋จผ์ ํ์ธ ๋ณด์!
https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#uploading-data-to-a-server
๊ณต์ ๋ฌธ์๋ฅผ ๋จผ์ ํ์ธํด์ ์ฐธ๊ณ ํ ๋งํ ์ฝ๋๋ฅผ ์ดํด๋ณด๊ณ > ๊ตฌ๊ธ๋ง์ผ๋ก ์ ์ ๋ฆฌํด๋ ๋ธ๋ก๊ทธ๋ฅผ ์ฐธ๊ณ ํด์ ๊ตฌํ > ๋ค์ ๊ณต์๋ฌธ์ ํ์ธ
์์๋ ๊ธฐ๋ฅ ๊ตฌํ๋ณด๋ค ํ์ต์ ๋ ์๊ฐ์ ๋ค์ด๊ณ ์ถ์ด์ ์ด๋ฐ ๋ฐฉ์์ผ๋ก ์งํํ๊ณ ์๋ค.
๊ณต์๋ฌธ์ ์์ - Uploading Multipart Form Data
AF.upload(multipartFormData: { multipartFormData in
multipartFormData.append(Data("one".utf8), withName: "one")
multipartFormData.append(Data("two".utf8), withName: "two")
}, to: "https://httpbin.org/post")
.responseDecodable(of: DecodableType.self) { response in
debugPrint(response)
}
ํ์ธํด๋ณด๋ฉด multipartFormData์ ๋ฐ์ดํฐ๋ฅผ ๋ด์ ํด๋ก์ ๋ฅผ ์ ๋ฌํ๊ณ , to์ URL์ ๋ด์์ฃผ๋ฉด ๋๋ค๋ ์ฌ์ค์ ์ ์ ์๋ค.
upload ๋ฉ์๋์ ์ฌ์ฉ๋๋ ์ ์ฒด ํ๋ผ๋ฏธํฐ๋ ๋ค์๊ณผ ๊ฐ๋ค.
func upload(
multipartFormData: @escaping (MultipartFormData) -> Void,
to url: URLConvertible,
usingThreshold encodingMemoryThreshold: UInt64 = MultipartFormData.encodingMemoryThreshold,
method: HTTPMethod = .post,
headers: HTTPHeaders? = nil,
interceptor: RequestInterceptor? = nil,
fileManager: FileManager = .default,
requestModifier: RequestModifier? = nil
) -> UploadRequest
func postImage(challengeId: Int, challengeName: String, image: UIImage) async throws -> AwsImage {
let url = "https://www.tistory.com/"
// API ์์ฒญ๋ถ๋ถ์ ํ์ธํด์ ํค๋๋ฅผ ๋ง๋ค์ด์ฃผ์
let headers: HTTPHeaders = [
"accept": "application/json",
"Content-Type": "multipart/form-data"
]
// ๋ฉ์๋์ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ์ image๋ฅผ jpeg์์ถํด์ฃผ์
let jpgImageData = image.jpegData(compressionQuality: 0.2) ?? Data()
// ์ด๋ฏธ์ง์ ์ ๋ณด๋ฅผ ๋ด์ upload ์ํ
let response = await AF.upload(
multipartFormData: { multipartFormData in
// Int ๊ฐ์ ๋ณด๋ผ ๋
multipartFormData.append(Data(String(challengeId).utf8),
withName: "challengeId")
// String ๊ฐ์ ๋ณด๋ผ ๋
multipartFormData.append(Data(challengeName.utf8),
withName: "challengeName")
// Data๋ก ๋ณํํ Image ๊ฐ ๋ณด๋ผ ๋
multipartFormData.append(jpgImageData,
withName: "file",
fileName: "image.png",
mimeType: "image/jpeg")},
to: url, method: .post, headers: headers)
.serializingDecodable(AwsResponse<AwsImage>.self) // ๋์ฝ๋ฉํ ๋ชจ๋ธ
.response
// response์ ๊ฒฐ๊ณผ์ ๋ฐ๋ผ ๋ถ๊ธฐ์ฒ๋ฆฌ
// 400~500๋ฒ๋์ ์๋ฌ์ผ ๊ฒฝ์ฐ ๋์ฝ๋ฉํ ์๋ต์์ ์๋ฌ ๋ฉ์์ง๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํด ์๋์ ๊ฐ์ด ์์ฑ
switch response.result {
case.success(let res):
if (400..<599).contains(response.response?.statusCode ?? 0) {
throw CustomError.invalidRequest(res.errMessage)
}
return res.data
case.failure(let error):
throw CustomError.invalidRequest(res.errMessage)
}
}
์ ์ํ์ธ์ ๐
- ํค๋์ "Content-Type": "multipart/form-data"๋ฅผ ๋ช ์ํด์ค์ผ ์๋ฒ์์ ์ ์์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ค.
- multipart ํต์ ์์๋ ์ผ๋ฐ์ ์ผ๋ก String, Int, Double๋ฑ์ ์๋ฃํ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ด๋ ๊ฒ์ด ์๋๋ผ, Dataํ์์ผ๋ก ๋ณด๋ด์ผ ํ๋ค.
์ด๋ฏธ์ง ์์ถ ๋ถ๋ถ
image.jpegData(compressionQuality: 0.2) ?? Data()
compressionQuality ์ซ์๊ฐ 0์ ๊ฐ๊น์ธ์๋ก ๋ง์ด ์์ถํ์ฌ ๋ฐ์ดํฐ ํฌ๊ธฐ๋ ์์์ง๋ฉฐ, ํ์ง์ด ๋จ์ด์ง๋ค.
compressionQuality ์ซ์๊ฐ 1์ ๊ฐ๊น์ธ์๋ก ์กฐ๊ธ ์์ถํ์ฌ ๋ฐ์ดํฐ ํฌ๊ธฐ๋ ๋น๊ต์ ํฌ๋ฉฐ, ํ์ง์ ์ ์ง๋๋ค.
0.2๋ก ์์ถํ๊ณ ์๋ฒ์ ์ ์กํ ๋ค์ ๋ค์ ๋ถ๋ฌ์ ํ์ธํ์ ๋ ์ดฌ์ํ ์ด๋ฏธ์ง(์๋ฒ์ ์ฌ๋ฆด ์ด๋ฏธ์ง)๊ฐ 500kb(์๋ฒ์์ ์ ํํ ๊ฐ)๊ฐ ๋์ง ์๊ณ ๊ธ์๋ฅผ ํ์ธํ ์ ์์ ์ ๋์ ํ์ง์ด์๊ธฐ ๋๋ฌธ์ ํด๋น ๊ฐ์ผ๋ก ํด๋์๋ค.
jpegData()๊ฐ nil์ผ ๊ฒฝ์ฐ์ Data()๋ฅผ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ํ๋ ๊ฒ ์๋ ์๋ ๋ก์ง์ด ์คํ๋์ง ์๋๋ก ์์ ํด์ผ๊ฒ ๋ค..!
์ด๋ฏธ์ง๋ฅผ ์ฌ๋ฌ์ฅ ์ ๋ก๋ํ ๊ฒฝ์ฐ
for๋ฌธ์ผ๋ก ์ด๋ฏธ์ง ๋ฐฐ์ด [uiImage]์ ๋๋ฉด์ multipartFormData์ appendํด์ฃผ๋ฉด ๋๋ค.
'๐ Apple > iOS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[iOS] ReactorKit ๋ค์ฌ๋ค๋ณด๊ธฐ (0) | 2024.05.17 |
---|---|
[iOS] ํ์ด์ด๋ฒ ์ด์ค ๊ตฌ๊ธ ๋ก๊ทธ์์/ํ์ํํด | Swift | Firebase Google Login (0) | 2024.01.13 |
[iOS] ๊ฐ๋ฐํ ๋ ์ ์ฉํ ์ฌ์ดํธ ๋ชจ์ ๐ (0) | 2023.12.31 |
[iOS] ATS(App Transport Security), ATS์ค์ ๋ฐฉ๋ฒ (0) | 2023.12.28 |
[iOS] Singleton ํจํด์ ํ์ฉํ๋ ๊ฒฝ์ฐ (0) | 2023.12.21 |