仅在 Swift 4.2 中上传带有多部分表单数据的图像

2023-11-21

我尝试了很多解决方案。我得到了一些,但他们正在使用objective c code在某处。我只需要解决方案swift 4.2并且没有任何第三方(例如Alamofire)。使用它工作正常objective c类。

我已经能够仅使用标头和其他参数以及图像发出 POST 请求,如下所示:

使用分段请求上传文件 - Swift 4

如何使用 Swift 进行多部分/表单数据发布请求?

多部分表单(图像、参数、标题)快速使用 Alamofire 发布请求

在 Swift 中上传带有多部分表单数据的图像 iOS

如何使用 Swift 将图像上传到 iOS 中的服务器?


func sendFile(
    urlPath:String,
    fileName:String,
    data:NSData,
    completionHandler: (NSURLResponse!, NSData!, NSError!) -> Void){

        var url: NSURL = NSURL(string: urlPath)!
        var request1: NSMutableURLRequest = NSMutableURLRequest(URL: url)

        request1.HTTPMethod = "POST"

        let boundary = generateBoundary()
        let fullData = photoDataToFormData(data,boundary:boundary,fileName:fileName)

        request1.setValue("multipart/form-data; boundary=" + boundary,
            forHTTPHeaderField: "Content-Type")

        // REQUIRED!
        request1.setValue(String(fullData.length), forHTTPHeaderField: "Content-Length")

        request1.HTTPBody = fullData
        request1.HTTPShouldHandleCookies = false

        let queue:NSOperationQueue = NSOperationQueue()

        NSURLConnection.sendAsynchronousRequest(
            request1,
            queue: queue,
            completionHandler:completionHandler)
}

// this is a very verbose version of that function
// you can shorten it, but i left it as-is for clarity
// and as an example
func photoDataToFormData(data:NSData,boundary:String,fileName:String) -> NSData {
    var fullData = NSMutableData()

    // 1 - Boundary should start with --
    let lineOne = "--" + boundary + "\r\n"
    fullData.appendData(lineOne.dataUsingEncoding(
        NSUTF8StringEncoding,
        allowLossyConversion: false)!)

    // 2
    let lineTwo = "Content-Disposition: form-data; name=\"image\"; filename=\"" + fileName + "\"\r\n"
    NSLog(lineTwo)
    fullData.appendData(lineTwo.dataUsingEncoding(
        NSUTF8StringEncoding,
        allowLossyConversion: false)!)

    // 3
    let lineThree = "Content-Type: image/jpg\r\n\r\n"
    fullData.appendData(lineThree.dataUsingEncoding(
        NSUTF8StringEncoding,
        allowLossyConversion: false)!)

    // 4
    fullData.appendData(data)

    // 5
    let lineFive = "\r\n"
    fullData.appendData(lineFive.dataUsingEncoding(
        NSUTF8StringEncoding,
        allowLossyConversion: false)!)

    // 6 - The end. Notice -- at the start and at the end
    let lineSix = "--" + boundary + "--\r\n"
    fullData.appendData(lineSix.dataUsingEncoding(
        NSUTF8StringEncoding,
        allowLossyConversion: false)!)

    return fullData
} 


请检查我的解决方案,它采用了参数和图像。我已经使用 PHP、.net、java 进行了测试。

class func request(withImages path:APIMethods, method:URLMethod, token : String?, headers:[String:String]?, parameters: [String:Any]?,imageNames : [String], images:[Data], completion: @escaping(Any?, Error?, Bool)->Void) {


    if !Reachability.isConnectedToNetwork() {
        DispatchQueue.main.async {
            showAlert(message: AppMessages.connectionFailed.rawValue)
        }
        dissmissHud()
        return
    }

    var stringUrl = "\(APIManager.url)\(APIMethods.preFix.rawValue)\(path.rawValue)"
    if method == .get, let lastPath = parameters?.values.first as? String {
        stringUrl += lastPath
    }else{
        stringUrl += token ?? ""
    }


    // generate boundary string using a unique per-app string
    let boundary = UUID().uuidString

    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)

    print("\n\ncomplete Url :-------------- ",stringUrl," \n\n-------------: complete Url")
    guard let url = URL(string: stringUrl) else { return }
    var request = URLRequest(url: url)
    request.httpMethod = method.rawValue

    if headers != nil{
        print("\n\nHeaders :-------------- ",headers as Any,"\n\n --------------: Headers")
        for (key, value) in headers! {
            request.setValue(value, forHTTPHeaderField: key)

        }
    }

    // Set Content-Type Header to multipart/form-data, this is equivalent to submitting form data with file upload in a web browser
    // And the boundary is also set here
    request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

    var data = Data()
    if parameters != nil{
        for(key, value) in parameters!{
            // Add the reqtype field and its value to the raw http request data
            data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
            data.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: .utf8)!)
            data.append("\(value)".data(using: .utf8)!)
        }
    }
    for (index,imageData) in images.enumerated() {
        // Add the image data to the raw http request data
        data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
        data.append("Content-Disposition: form-data; name=\"\(imageNames[index])\"; filename=\"\(imageNames[index])\"\r\n".data(using: .utf8)!)
        data.append("Content-Type: image/jpeg\r\n\r\n".data(using: .utf8)!)
        data.append(imageData)
    }

    // End the raw http request data, note that there is 2 extra dash ("-") at the end, this is to indicate the end of the data
    data.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)

    // Send a POST request to the URL, with the data we created earlier
    session.uploadTask(with: request, from: data, completionHandler: { data, response, error in

        if let checkResponse = response as? HTTPURLResponse{
            if checkResponse.statusCode == 200{
                guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: [JSONSerialization.ReadingOptions.allowFragments]) else {
                    completion(nil, error, false)
                    return
                }
                let jsonString = String(data: data, encoding: .utf8)!
                print("\n\n---------------------------\n\n"+jsonString+"\n\n---------------------------\n\n")
                print(json)
                completion(json, nil, true)
            }else{
                guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) else {
                    completion(nil, error, false)
                    return
                }
                let jsonString = String(data: data, encoding: .utf8)!
                print("\n\n---------------------------\n\n"+jsonString+"\n\n---------------------------\n\n")
                print(json)
                completion(json, nil, false)
            }
        }else{
            guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) else {
                completion(nil, error, false)
                return
            }
            completion(json, nil, false)
        }

    }).resume()

}

extension Data {

    /// Append string to Data
    ///
    /// Rather than littering my code with calls to `data(using: .utf8)` to convert `String` values to `Data`, this wraps it in a nice convenient little extension to Data. This defaults to converting using UTF-8.
    ///
    /// - parameter string:       The string to be added to the `Data`.

    mutating func append(_ string: String, using encoding: String.Encoding = .utf8) {
        if let data = string.data(using: encoding) {
            append(data)
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

仅在 Swift 4.2 中上传带有多部分表单数据的图像 的相关文章

随机推荐

  • 当前页面的 UIPageControl 点大小[重复]

    这个问题在这里已经有答案了 我试图找出如何使所选页面的点比其他页面稍大 如下所示 Page 1 Page 2 我可以更改点的颜色 大小all点 背景等 但不适用于specific当前页面的点 如何仅更改当前页面的点大小 这可以是 Swift
  • 删除整个 PHP 类

    class foo 假设该类存在于我的代码中 然后我不再需要该类并希望将其删除 以便稍后我可以用新类替换它 是否可以从运行时删除整个类 不可以 您不能在运行时删除或大幅修改 PHP 类 或函数
  • 处理错误后跳过承诺链

    使用https github com kriskowal q图书馆 我想知道是否可以做这样的事情 Module A function moduleA exportedFunction return promiseReturningServi
  • 从 ActiveDirectory 检索用户帐户到期时间

    我正在尝试从帐户中检索到期日期 我试过了 DirectoryEntry user new DirectoryEntry iMem var AccountExpiration DateTime FromFileTime int user Pr
  • 为什么 Task 比 ValueTask 更快?

    我正在做一个基准测试Task
  • 在 ActionBarSherlock 中将标题重力设置为中心

    您好 我想为我的主要活动应用自定义背景布局 我找不到解决办法 有人可以给我一些建议吗 希望在操作栏中有一个简单的带有背景的 TextView 这可能吗 我设法删除图标并设置背景图像 但是如何将文本的重力设置为居中并更改字体呢 getSupp
  • 如何获得连续的触摸事件?

    我的类扩展了 View 我需要在其上获取连续的触摸事件 如果我使用 public boolean onTouchEvent MotionEvent me if me getAction MotionEvent ACTION DOWN myA
  • 如何将 json 加载到我的 angular.js ng-model 中?

    我有一个我认为可能是一个非常明显的问题 但我无法在任何地方找到答案 我只是想将一些 JSON 数据从我的服务器加载到客户端 现在 我正在使用 JQuery 通过 AJAX 调用加载它 代码如下 它位于 html 文件中 到目前为止它有效 但
  • WPF 工具包数据网格单元格文本换行

    我的 WPF 数据网格的列是固定宽度的 这意味着行中的长文本被截断 我怎样才能让文字换行 如果您使用的是 DataGridTextColumn 则需要定义 DataGridTextColumn ElementStyle 的样式
  • Reactjs - 如何将值从子组件传递到祖父组件?

    下面是在reactjs中将值从子组件传递到父组件的正确示例 App jsx import React from react class App extends React Component constructor props super
  • 如何访问其他程序内存中的结构?

    我知道如何在 C 中导入和使用读 写进程内存 我正在做游戏训练师 我需要 直接 访问转换为结构的其他进程内存 我可以使用 readprocessmemory 或 writeprocessmemory 但这需要很多时间来实现许多结构 C 中有
  • 在旧的 Borland C 中使用 Visual C++ DLL?

    我必须支持使用旧的 Borland 编译器 BC 5 用 C 编写的旧应用程序 不幸的是 我们使用的旧 TCP IP 库开始显示出它的年龄 并且在 Vista 和 Win7 机器上出现问题 我有一个可用于 MS Visual C 的新函数库
  • 如何提取ctree()终端节点的分裂规则

    我有一个包含 6 个分类变量的数据集 级别范围从 5 到 28 我已获得以下输出 ctree 派对包 有 17 个终端节点 我已关注 Galled 的输入ctree 如何获取每个终端节点的分裂条件列表 达到我想要的输出 但是 我在运行代码时
  • $resource `get` 函数如何在 AngularJS 中同步工作?

    我当时正在看thisAngularJS 教程描述了如何使用 Angular 资源连接 Twitter 视频教程 这是在示例控制器中设置的资源 scope twitter resource http twitter com action ac
  • 使用 PHP 获取 TrueType 中可用的字符

    如何获取 TrueType 字体中所有可用字符的列表 使用 PHP PHP 似乎没有任何可用的扩展directly with FreeType 处理 TrueType 字体的统治性开源库 您可能需要使用适当的库来使用另一种语言 例如Perl
  • ModuleNotFoundError:没有名为“django”的模块

    我正在尝试在线制作一个项目 但出现一个我无法解决的错误 我已经安装了 django 但服务器给我这个错误 Virtualenv 也处于活动状态 2017 09 25 20 10 27 471 2017 09 25 20 10 30 892
  • 无法将 ListBox.ObjectCollection 转换为(类型化)数组

    我想将项目转换为字符串数组或我用来填充 ListBox DataSource 的类型 该类型已覆盖 ToString 但我似乎无法将其转换 甚至无法转换为 String String a String ListBox1 Items Cont
  • Cognito 用户池触发器上的 AWS Lambda 错误

    我正在尝试将一条记录插入到 DynamoDB 中 调用 Cognito 用户池的 预注册 触发器 出于测试目的 Lambda 函数非常简单 但在 AWSCognito CognitoIdentityServiceProvider Cogni
  • 刚刚开始出现 AIR SQLite 错误 3182 发生磁盘 I/O 错误

    我们的软件有一个新的测试版 进行了一些更改 但不是围绕我们的数据库层 我们刚刚开始在服务器日志中报告错误 3128 似乎一旦发生 只要应用程序打开 它就会发生 代码中最明显的部分是我们通过 SQLite 每秒记录数据的部分 仅这个月我们的服
  • 仅在 Swift 4.2 中上传带有多部分表单数据的图像

    我尝试了很多解决方案 我得到了一些 但他们正在使用objective c code在某处 我只需要解决方案swift 4 2并且没有任何第三方 例如Alamofire 使用它工作正常objective c类 我已经能够仅使用标头和其他参数以