简体   繁体   English

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

[英]Upload image with multipart form-data only in Swift 4.2

I tried lots of solution.我尝试了很多解决方案。 I get some but they were using objective c code in somewhere.我得到了一些,但他们在某处使用了objective c code I need solution only in swift 4.2 and without any third party (like Alamofire ).It is working fine using objective c classes .我只需要swift 4.2解决方案,不需要任何第三方(如Alamofire )。使用objective c classes 工作正常。

I have been able to make POST request with only, headers and other parameters and image as:我已经能够仅使用标头和其他参数以及图像发出 POST 请求:

Upload files using multipart request - Swift 4 使用多部分请求上传文件 - Swift 4

How to do multipart/form-data post request with Swift? 如何使用 Swift 进行多部分/表单数据发布请求?

Multipart-form (image,parameters,headers) Post request with Alamofire in swift Multipart-form (image,parameters,headers) 使用 Alamofire 快速发布请求

Upload image with multipart form-data iOS in Swift 使用 Swift 中的多部分表单数据 iOS 上传图像

How to upload images to a server in iOS with Swift? 如何使用 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
} 

Please check my solution which is taken parameters and images.I have tested with PHP, .net, java.请检查我的解决方案,它采用了参数和图像。我已经用 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)
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Swift - 包含和不包含图像的multipart / form-data POST请求(上传) - Swift - multipart/form-data POST request(upload) with and without image 在 Swift 中上传带有多部分表单数据 iOS 的图像 - Upload image with multipart form-data iOS in Swift 如何在 Swift 中使用 Codable 和 URLSession.shared.uploadTask (multipart/form-data) 上传图像文件? - How to upload image file using Codable and URLSession.shared.uploadTask (multipart/form-data) in Swift? 在Swift中上传包含多部分/表单数据的图像和参数 - Uploading an image and parameters with multipart/form-data in Swift 快速上传多部分/表单数据,并将字符串数组附加到主体(问题:数组作为字符串发送到服务器) - Swift multipart/form-data upload with append String Array to body (Issue: Array goes as String to Server) 我想使用 alamofire swift 5 将图像上传到多部分表单数据 - I want to upload image to multipart form data using alamofire swift 5 swift url Session 带有参数和图像的发布请求(多部分表单数据请求) - swift url Session post request with parameters and image (Multipart Form-Data Requests ) 无法将带有 multipart/form-data 的图片上传到服务器 - Failing to Upload Picture with multipart/form-data to a Server AFNetworking 2.0多部分/表单数据上传到mySQL - AFNetworking 2.0 multipart/form-data upload to mySQL URLSessionDataTask - 上传具有 multipart/form-data 内容类型的参数 - URLSessionDataTask - upload parameters with multipart/form-data content type
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM