在 HTTP 通信中,Body(主体) 是承载实际业务数据的容器。服务器通过 Content-Type 请求头来判断如何解析这些二进制数据。
以下是 iOS 开发中最常见的四种 Body 格式及其处理方式:
1. JSON (application/json)
这是现代移动端开发(RESTful API)的绝对标准。数据结构清晰,易于跨平台解析。
-
iOS 处理方式:使用
JSONEncoder将 Swift 结构体序列化为Data。 -
代码示例:
Swift
struct User: Encodable { let name: String; let id: Int } let user = User(name: "Gemini", id: 101) var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Content-Type") // 将对象转为 Data 放入 Body request.httpBody = try? JSONEncoder().encode(user)
2. Form URL Encoded (application/x-www-form-urlencoded)
传统的浏览器表单提交格式。数据以键值对形式呈现,并经过 URL 编码,类似 name=Gemini&id=101。
-
iOS 处理方式:手动拼接字符串并转换为
Data,或使用URLComponents构造查询字符串。 -
代码示例:
Swift
var components = URLComponents() components.queryItems = [ URLQueryItem(name: "username", value: "admin"), URLQueryItem(name: "password", value: "123456") ] // 注意:这里取的是 query 字符串部分作为 Body request.httpBody = components.query?.data(using: .utf8) request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
3. Multipart Form Data (multipart/form-data)
当请求中既有文本又有文件(如图片、视频)时,必须使用此格式。它通过一个特殊的 boundary 字符串将不同部分分隔开。
- iOS 处理方式:原生
URLSession处理起来比较繁琐,需要手动拼接复杂的二进制协议头;生产环境通常使用 Alamofire。 - 逻辑结构:
4. Binary / Raw (application/octet-stream)
直接发送原始二进制流。常用于纯文件上传(如直接上传一个 .png 或 .zip),不包含其他文本字段。
-
iOS 处理方式:直接读取文件
Data并赋值给httpBody。 -
代码示例:
Swift
let imageData = UIImage(named: "avatar")?.jpegData(compressionQuality: 0.8) request.httpBody = imageData request.setValue("image/jpeg", forHTTPHeaderField: "Content-Type")
核心对比表
| 格式名称 | Content-Type | 适用场景 | iOS 核心工具 |
|---|---|---|---|
| JSON | application/json | 绝大多数 API、复杂嵌套数据 | JSONEncoder |
| Form | ...x-www-form-urlencoded | 登录、简单键值对、旧版接口 | URLComponents |
| Multipart | multipart/form-data | 混合上传(图片+描述) | Data 拼接 / Alamofire |
| Plain Text | text/plain | 纯文本、简单的日志上传 | String.data(using:) |
💡 避坑指南
- 忘记设置 Content-Type:这是最常见的错误。如果你发送了 JSON Body 但没设 Header,服务器可能会报
400 Bad Request。 - Get 请求带 Body:虽然技术上可行,但 HTTP 规范不建议这样做,很多代理服务器(如 Nginx)会直接无视 GET 请求的 Body。
- 大文件上传:对于极大的文件,不要直接赋值给
request.httpBody(这会占用大量内存),而应使用URLSession.shared.uploadTask(with:fromFile:)。