You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS Swift使用Alamofire multipart form data上传文件与图片问题

Alamofire 多类型文件上传兼容方案

核心改造思路

  • 定义枚举封装上传资源类型,显式区分图片/普通文件,避免类型判断错误
  • 修正原有请求头错误:上传multipart表单时不需要手动指定Content-Type为application/json,Alamofire会自动生成带边界标识的正确请求头
  • 根据资源类型分别处理数据、文件名、MIME类型的拼接

类型判断逻辑

如果仅需要区分资源类型,可直接读取文件后缀/资源标识判断:

  • 后缀为jpg/jpeg/png判定为图片类资源
  • 后缀为txt/pdf判定为普通文件类资源

完整改造代码

第一步:定义资源类型枚举

enum UploadResumeResource {
    // 关联值:图片本身 + 图片格式,默认JPG格式
    case image(UIImage, format: ImageFormat = .jpg)
    // 关联值:本地文件路径
    case file(URL)
    
    enum ImageFormat {
        case jpg(compressionQuality: CGFloat = 1.0)
        case png
    }
    
    // 获取对应MIME类型
    var mimeType: String {
        switch self {
        case .image(_, let format):
            switch format {
            case .jpg: return "image/jpeg"
            case .png: return "image/png"
            }
        case .file(let fileUrl):
            let ext = fileUrl.pathExtension.lowercased()
            switch ext {
            case "txt": return "text/plain"
            case "pdf": return "application/pdf"
            case "jpg", "jpeg": return "image/jpeg"
            case "png": return "image/png"
            default: return "application/octet-stream"
            }
        }
    }
    
    // 获取对应文件二进制数据
    var fileData: Data? {
        switch self {
        case .image(let image, let format):
            switch format {
            case .jpg(let quality): return image.jpegData(compressionQuality: quality)
            case .png: return image.pngData()
            }
        case .file(let fileUrl):
            return try? Data(contentsOf: fileUrl)
        }
    }
    
    // 获取对应文件名
    var fileName: String {
        switch self {
        case .image(_, let format):
            switch format {
            case .jpg: return "resume.jpg"
            case .png: return "resume.png"
            }
        case .file(let fileUrl):
            return fileUrl.lastPathComponent
        }
    }
}

第二步:改造上传函数

func postResume(resource: UploadResumeResource) {
    // 移除错误的Content-Type配置,Alamofire会自动生成multipart表单对应的请求头
    let headers: HTTPHeaders = [
        "Accept": "application/json"
    ]
    
    let url = Constants.BASEURL.baseUrl + Constants.URLEXTENSIONS.getAnswers
    
    AF.upload(multipartFormData: { multipartFormData in
        guard let data = resource.fileData else { return }
        multipartFormData.append(data, withName: "resume", fileName: resource.fileName, mimeType: resource.mimeType)
    }, to: url, headers: headers).responseJSON { response in
        switch response.result {
        case .success(let value):
            // 保留原有成功处理逻辑
            break
        case .failure(let error):
            DispatchQueue.main.async {
                // 保留原有失败处理逻辑
            }
            break
        }
    }
}

调用示例

  • 上传JPG格式图片
let resumeImage = UIImage(named: "resume")!
postResume(resource: .image(resumeImage, format: .jpg(compressionQuality: 0.8)))
  • 上传本地PDF文件
let pdfUrl = Bundle.main.url(forResource: "resume", withExtension: "pdf")!
postResume(resource: .file(pdfUrl))
  • 上传本地TXT文件
let txtUrl = Bundle.main.url(forResource: "resume", withExtension: "txt")!
postResume(resource: .file(txtUrl))

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 22:18:03