You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何向API上传数据?基于现有代码的技术咨询

完整实现API数据上传的指南

我来帮你把这段代码补全并优化,实现规范的multipart/form-data格式API上传。先说说你现有代码里的几个关键问题:没设置multipart必需的边界(boundary)、网络任务根本没启动、缺少完整的错误和响应处理,还有请求体的构造也不符合标准格式。

1. 完整优化后的代码实现

import Foundation

class TaskManager {
    static let httpString = "你的实际API基础地址" // 记得替换成真实地址
    static let boundary = "Boundary-\(UUID().uuidString)" // 生成唯一边界值,避免数据冲突

    /// 上传数据到API
    /// - Parameters:
    ///   - uploadData: 要上传的原始数据
    ///   - fileName: 上传文件的名称(可选,默认file.dat)
    ///   - completion: 上传结果回调,主线程执行,方便更新UI
    static func uploadNewInfo(uploadData: Data, fileName: String = "file.dat", completion: @escaping (Bool, String?) -> Void) {
        // 校验API地址有效性
        guard let url = URL(string: httpString + "sett_eic.htm") else {
            completion(false, "无效的API地址,请检查基础URL配置")
            return
        }

        // 构造请求
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        // 设置正确的Content-Type,必须带boundary参数
        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

        // 构造符合multipart格式的请求体
        let httpBody = createMultipartBody(with: uploadData, fileName: fileName)
        request.httpBody = httpBody

        // 创建并启动网络任务
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            // 切回主线程回调,避免UI操作报错
            DispatchQueue.main.async {
                // 处理网络错误
                if let error = error {
                    completion(false, "上传失败:\(error.localizedDescription)")
                    return
                }

                // 校验HTTP响应状态码
                guard let httpResponse = response as? HTTPURLResponse,
                      (200...299).contains(httpResponse.statusCode) else {
                    let statusCode = (response as? HTTPURLResponse)?.statusCode ?? -1
                    completion(false, "服务器响应错误,状态码:\(statusCode)")
                    return
                }

                // 解析服务器返回内容(如果需要)
                if let data = data, let responseString = String(data: data, encoding: .utf8) {
                    print("服务器返回内容:\(responseString)")
                    completion(true, responseString)
                } else {
                    completion(true, nil)
                }
            }
        }
        // 启动任务!这是你原有代码漏掉的核心步骤
        task.resume()
    }

    /// 构造符合multipart/form-data规范的请求体
    private static func createMultipartBody(with data: Data, fileName: String) -> Data {
        let body = NSMutableData()

        // 添加字段头部描述
        body.append("--\(boundary)\r\n".data(using: .utf8)!)
        body.append("Content-Disposition: form-data; name=\"file\"; filename=\"\(fileName)\"\r\n".data(using: .utf8)!)
        // 根据你上传的文件类型调整Content-Type,比如图片用image/jpeg,JSON用application/json
        body.append("Content-Type: application/octet-stream\r\n\r\n".data(using: .utf8)!)
        // 添加要上传的原始数据
        body.append(data)
        body.append("\r\n".data(using: .utf8)!)

        // 添加结束边界
        body.append("--\(boundary)--\r\n".data(using: .utf8)!)

        return body as Data
    }
}

2. 关键细节说明

  • Boundary的必要性multipart/form-data必须用唯一的边界值分隔不同字段,防止和上传数据内容冲突,这里用UUID生成绝对唯一的边界。
  • 请求体规范createMultipartBody方法严格按照HTTP协议要求包装数据,包含字段名称、文件名、内容类型等元信息,确保服务器能正确解析。
  • 启动网络任务:原有代码只创建了dataTask但没调用task.resume(),这会导致任务完全不执行,一定要加上!
  • 回调机制:添加了逃逸闭包completion,方便调用者获取上传结果,而且强制在主线程回调,避免更新UI时出现线程错误。
  • 完整错误处理:覆盖了网络错误、无效地址、服务器异常响应等场景,让你能快速定位问题。

3. 调用示例

// 假设你已经准备好要上传的数据
let testData = "这是测试上传的内容".data(using: .utf8)!

// 调用上传方法
TaskManager.uploadNewInfo(uploadData: testData, fileName: "test.txt") { success, message in
    if success {
        print("上传成功!服务器返回:\(message ?? "无返回内容")")
        // 这里可以添加成功后的UI操作,比如弹出提示框
    } else {
        print("上传失败:\(message ?? "未知错误")")
        // 处理失败逻辑,比如重新上传或提示用户
    }
}

4. 注意事项

  • Content-Type调整:如果上传的是图片、JSON等特定类型文件,要修改createMultipartBody里的Content-Type值,比如图片用image/png,JSON用application/json
  • ATS配置:如果你的API是HTTP协议(非HTTPS),需要在iOS项目的Info.plist中添加ATS允许配置,否则会被系统拦截。
  • 权限检查:如果上传的是相册、文件等敏感数据,要确保已经获取了对应的系统权限。

内容的提问来源于stack exchange,提问作者user9413278

火山引擎 最新活动