BOYYANG/1/blog/compressed/Yor-Forger-Spy-x-Family-fan-art-digital-art-artwork-illustration-2218660-wallhere

swift ui 如何使用Alamofire上传文件,并且附带formData参数

作者: boyyang
分类: Swift
发布: 2025-05-16 09:18:13
更新: 2025-05-16 09:32:57
浏览: 111

背景

最近在使用swift ui开发ios原生应用,由于使用的是Alamofire向后端请求数据,一般的get,post请求都还正常,但是当我需要上传图片的时候,我查了一下文档,Alamofire是有提供formData上传文件的。文件上传是解决了,但是我该怎么在上传文件的同时附带额外的参数呢,比如说文件上传到后端的哪个储存桶,文件压缩质量等等。这个时候我就不知道该怎么处理了。

在此之前先介绍一下Alamofire是什么吧。

Alamofire是什么

Alamofire 是一个用于 Swift 编程语言的强大且流行的 HTTP 网络库。它由 Alamofire 团队开发和维护,旨在简化网络请求的处理,使开发者能够更高效地进行网络编程。

主要特点包括:

  1. 简洁易用:Alamofire 提供了简洁的 API,使得发送 HTTP 请求变得非常简单。
  2. 功能强大:支持各种 HTTP 方法(GET、POST、PUT、DELETE 等),以及多种数据传输方式(JSON、URL 编码、多部分表单等)。
  3. 错误处理:提供了详细的错误处理机制,帮助开发者快速定位和解决问题。
  4. 链式调用:支持链式调用,使得请求配置和响应处理更加灵活。
  5. 支持多种数据格式:支持 JSON、XML、Plist 等多种数据格式。
  6. 后台任务支持:可以在后台线程中执行网络请求,不会阻塞主线程。
  7. 安全性:支持 HTTPS,并且可以配置 SSL/TLS 以确保数据传输的安全性。

Alamofire如何使用

使用 Alamofire 进行网络请求非常简单。以下是一个基本的 GET 请求示例:

首先,确保你已经将 Alamofire 添加到你的项目中。如果你使用的是 Swift Package Manager,可以在 Package.swift 文件中添加 Alamofire 依赖(我是之间通过git仓库地址在xcode里面直接搜索添加到项目中的):

// swift-tools-version:5.3
import PackageDescription

let package = Package(
    name: "YourProjectName",
    dependencies: [
        .package(url: "https://github.com/Alamofire/Alamofire.git", from: "5.4.3")
    ],
    targets: [
        .target(
            name: "YourTargetName",
            dependencies: ["Alamofire"])
    ]
)

具体使用:

import Alamofire

Alamofire.request("https://api.example.com/data")
    .responseJSON { response in
        switch response.result {
        case .success(let value):
            if let json = value as? [String: Any] {
                print("JSON: \(json)")
            }
        case .failure(let error):
            print("Error: \(error)")
        }
    }

如何上传文件

//
//  UPLOAD.swift
//  Unsplash
//
//  Created by boyyang on 2025/4/29.
//

import SwiftUI
import Alamofire

public struct UploadRes: Decodable {
    var id: String
    var file_name: String
    var path: String
    var origin_path: String
}

public struct AlamofireAsync {
    
    @AppStorage("token") var token: String = ""
    
    static let shared = AlamofireAsync()
    
    let uploadUrl = "http://localhost:8888/image/upload/bytes"
  
    func request(file: Data, fileName: String, dir: String, type: String) async throws -> Response<UploadRes> {
        return try await withCheckedThrowingContinuation { continuation in
            let headers: HTTPHeaders = [
                "Content-type": "multipart/form-data",
                "Authorization": token,
            ]
            
            AF.upload(
                multipartFormData: {multipartFormData in
                    multipartFormData.append(file, withName: "file", mimeType: "image")
                    multipartFormData.append(fileName.data(using: .utf8, allowLossyConversion: false)!, withName: "file_name")
                    multipartFormData.append("wallpaper".data(using: .utf8, allowLossyConversion: false)!, withName: "bucket_name")
                    multipartFormData.append("IMAGES".data(using: .utf8, allowLossyConversion: false)!, withName: "root_dir")
                    multipartFormData.append(dir.data(using: .utf8, allowLossyConversion: false)!, withName: "dir")
                    multipartFormData.append("10".data(using: .utf8, allowLossyConversion: false)!, withName: "quality")
                    multipartFormData.append("1".data(using: .utf8, allowLossyConversion: false)!, withName: "status")
                    multipartFormData.append(type.data(using: .utf8, allowLossyConversion: false)!, withName: "type")
                },
                to: uploadUrl,
                method: .post ,
                headers: headers,
    
            ).responseDecodable(of: Response<UploadRes>.self) { res in
                switch res.result {
                case .success(let resp):
                    continuation.resume(returning: resp)
                case .failure(let err):
                    continuation.resume(throwing: err)
                }
            }
        }
    }

值得一提的是如果你想在上传文件的同时附带一下参数,你得通过multipartFormData.append("IMAGES".data(using: .utf8, allowLossyConversion: false)!, withName: "root_dir")
这种方式上传额外的参数,withName就是上传参数的名称,前面的是上传参数的值。我之前就是把这2个给搞反了,导致我的后端一直获取不到参数,我还在到处寻找问题。

#前端
#后端
#swift
#swift ui
#Alamofire
#文件上传