Swift
Image Upload
iOS Development
HTTP `Parameters`
Swift Programming

Upload image with parameters in Swift

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Uploading an image together with extra fields in Swift usually means sending a multipart/form-data request. The server receives one part for the image bytes and separate parts for text parameters such as user IDs, captions, or flags.

Build a Multipart Request

The main pieces are:

  • a URLRequest
  • a unique multipart boundary
  • text fields appended as form parts
  • image data appended as a file part

Here is a complete example with URLSession:

swift
1import Foundation
2import UIKit
3
4func uploadImage(
5    image: UIImage,
6    parameters: [String: String],
7    to url: URL
8) async throws -> Data {
9    guard let imageData = image.jpegData(compressionQuality: 0.8) else {
10        throw URLError(.cannotEncodeContentData)
11    }
12
13    let boundary = UUID().uuidString
14    var request = URLRequest(url: url)
15    request.httpMethod = "POST"
16    request.setValue(
17        "multipart/form-data; boundary=\(boundary)",
18        forHTTPHeaderField: "Content-Type"
19    )
20
21    var body = Data()
22
23    for (key, value) in parameters {
24        body.append("--\(boundary)\r\n".data(using: .utf8)!)
25        body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: .utf8)!)
26        body.append("\(value)\r\n".data(using: .utf8)!)
27    }
28
29    body.append("--\(boundary)\r\n".data(using: .utf8)!)
30    body.append("Content-Disposition: form-data; name=\"image\"; filename=\"upload.jpg\"\r\n".data(using: .utf8)!)
31    body.append("Content-Type: image/jpeg\r\n\r\n".data(using: .utf8)!)
32    body.append(imageData)
33    body.append("\r\n".data(using: .utf8)!)
34    body.append("--\(boundary)--\r\n".data(using: .utf8)!)
35
36    let (data, response) = try await URLSession.shared.upload(for: request, from: body)
37
38    guard let httpResponse = response as? HTTPURLResponse,
39          (200...299).contains(httpResponse.statusCode) else {
40        throw URLError(.badServerResponse)
41    }
42
43    return data
44}

This function creates the body manually, which is often the simplest pure-Foundation solution.

Call It from App Code

Example usage:

swift
1import UIKit
2
3Task {
4    do {
5        let image = UIImage(systemName: "person.circle")!
6        let url = URL(string: "https://example.com/upload")!
7
8        let responseData = try await uploadImage(
9            image: image,
10            parameters: [
11                "userId": "42",
12                "caption": "Profile photo"
13            ],
14            to: url
15        )
16
17        print(String(decoding: responseData, as: UTF8.self))
18    } catch {
19        print("Upload failed:", error)
20    }
21}

In a real app, the image usually comes from the camera, photo library, or an edited image pipeline rather than a system symbol.

Why Multipart Is Required

A JSON request is not the normal format for raw image upload because binary image bytes and text form values need different treatment. multipart/form-data solves that by separating each field into a distinct part with its own headers.

That is why the boundary matters. It marks where one field ends and the next begins. If the boundary or line endings are wrong, the server will often reject the request even though the code compiles.

Choose the Right Image Encoding

jpegData(compressionQuality:) is appropriate for photos. For images that need transparency, such as stickers or icons, PNG may be more appropriate:

swift
let imageData = image.pngData()

The server and the declared MIME type must match the actual bytes you send.

Handle Server Contracts Explicitly

The field names in your multipart body must match what the server expects. If the backend expects file instead of image, or user_id instead of userId, the request can succeed technically while still failing semantically.

Good upload code is not just about HTTP syntax. It also has to match the backend contract exactly.

Common Pitfalls

  • Forgetting the closing boundary at the end of the multipart body.
  • Declaring image/jpeg while actually sending PNG data, or the reverse.
  • Using parameter names that do not match the server contract.
  • Ignoring non-2xx status codes and treating any response body as success.
  • Building the request correctly but uploading an image representation that is unexpectedly large for mobile networks.

Summary

  • To upload an image with extra fields in Swift, use a multipart/form-data request.
  • Build the request body with a boundary, text parameters, and a file part for the image.
  • Make sure the MIME type matches the actual image encoding.
  • Validate the HTTP status code instead of assuming the upload succeeded.
  • Server field names and multipart formatting must match the backend contract exactly.

Course illustration
Course illustration

All Rights Reserved.