如何将带有表单数据的图像上传到api参数中?

Posted

技术标签:

【中文标题】如何将带有表单数据的图像上传到api参数中?【英文标题】:how to upload image with form data which image is on parameter to api? 【发布时间】:2019-04-16 06:39:15 【问题描述】:

我需要上传带有表单数据的图片,但我的图片总是没有发送到 api

我的参数是这样的

nickname": "carex",
password: "mantap",
name : "Kopral Kapten",
nickname : "cobra",
email : "ularkobra@gmail.com",
birth_date : "1980-09-29",
gender : "m",
phone : "081908908890",
password : "Vb+2fzEf/kXZuHUPenfT+Q==",
city : "Malang",
picture: upload file

我的代码:

if let data = imageData 

            let imageURL = imageUrl
            let fileName = imageURL.absoluteString

            let userId = UserDefaults.standard.object(forKey: "id") as! String
            let token =  UserDefaults.standard.object(forKey: "token") as! String

            let Params : Parameters = [
                "picture" : fileName
            ]

            //filename is image

            let headersku: HTTPHeaders = [
                "Content-Type":"application/x-www-form-urlencoded",
                "Authorization": "Bearer \(token)"
            ]

            let base_Url = "https://dev.lenna.ai/lenna/public/api/dBmK5m/users/\(userId)"

            // Start Alamofire

            Alamofire.upload(multipartFormData: multipartFormData in
                multipartFormData.append(data, withName: "image", fileName: fileName, mimeType: "image/jpeg")
                for (key, value) in Params 
                        multipartFormData.append((value as! String).data(using: String.Encoding.utf8)!, withName: key )
                

                ,
                             usingThreshold:UInt64.init(),
                             to: base_Url,
                             method:.post,
                             headers: headersku,
                             encodingCompletion:  encodingResult in
                                switch encodingResult 
                                case .success(let upload, _, _):
                                    upload.responseJSON  response in
                                        print(response)

                                        self.userImg.image = image
                                    
                                case .failure(let encodingError):
                                    print(encodingError)
                                
            )

        

【问题讨论】:

***.com/questions/55098495/… https://***.com/questions/49047698/how-to-upload-audio-with-alamofire-multipart-upload/49047796#49047796 【参考方案1】:

试试这个,你需要将图像作为多部分发送,或者你需要将图像作为数据格式附加到 params 字典中

let image: UIImage? = self.uploadImg.image

let uploadDict = ["key":val] as [String:String]

Alamofire.upload(multipartFormData:  MultipartFormData in

        let image :Data = (image?.jpegData(compressionQuality: 1))!

        MultipartFormData.append(image, withName: "image" , fileName: "image.jpeg" , mimeType: "image/jpeg")
        for(key,value) in uploadDict

            MultipartFormData.append(value.data(using: String.Encoding.utf8)!, withName: key)

    , to: "http://XXXXXXXXXXXXXXXX/uploadImage", encodingCompletion: 
        EncodingResult in
        switch EncodingResult
        case .success(let upload, _, _):
            upload.responseJSON  response in
                debugPrint("SUCCESS RESPONSE: \(response)")
            
        case .failure(let encodingError):

            print("ERROR RESPONSE: \(encodingError)")

                    
    )

【讨论】:

【参考方案2】:

试试这个,你可以在body中添加其他参数

    func uploadImage(image: UIImage)


    let url = URL(string: "URL_TO_php_SERVER");
    let request = NSMutableURLRequest(url: url!)
    request.httpMethod = "POST"

    let boundary = generateBoundaryString()

    //define the multipart request type

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

    let image_data = UIImageJPEGRepresentation(image, 1)


    if(image_data == nil)
    
        print("problem occurred")
        return;
    


    let body = NSMutableData();

    let date = Date();
    let fname = "\(Int64(date.timeIntervalSince1970*1000)).jpg"
    print("file name: \(fname)");
    let mimetype = "image/jpeg"

    //define the data post parameter

    body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
    body.append("Content-Disposition:form-data; name=\"test\"\r\n\r\n".data(using: String.Encoding.utf8)!)
    body.append("hi\r\n".data(using: String.Encoding.utf8)!)

    body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
    body.append("Content-Disposition:form-data; name=\"file\"; filename=\"\(fname)\"\r\n".data(using: String.Encoding.utf8)!)
    body.append("Content-Type: \(mimetype)\r\n\r\n".data(using: String.Encoding.utf8)!)
    body.append(image_data!)
    body.append("\r\n".data(using: String.Encoding.utf8)!)


    body.append("--\(boundary)--\r\n".data(using: String.Encoding.utf8)!)



    request.httpBody = body as Data


    //        let session = NSURLSession.sharedSession()
    var configuration = URLSessionConfiguration.default;
    var session = URLSession(configuration: configuration, delegate: self, delegateQueue: OperationQueue.main);


    let task = session.dataTask(with: request as URLRequest) 
        (
        data, response, error) in

        guard let _:Data = data, let _:URLResponse = response, error == nil else 
            print("error")
            DispatchQueue.main.async 
                print("Problem occurred in uploading");
                // DO your stuff in UI Thread
            
            return
        

        DispatchQueue.main.async 
            print("uploading success");
            // DO your stuff in UI Thread
        

        let dataString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
        print(dataString)

    

    task.resume()



【讨论】:

【参考方案3】:

您需要在 params 字典中将图像作为多部分发送

    import Alamofire

    func tempImageShareToApi()

        let apiURL = "http://testApp/public/api/user/profile"
        let params : [String: String] = [
            "id"             : "\(UserId)"
        ]

        print(params)
        Alamofire.upload(multipartFormData:  (multipartFormData) in

            if let normalImg = self.userImageView 
                if  let imgValue = (self.pickedImage?.jpegData(compressionQuality: 0.75)) 
                    let r = arc4random()
                    let str = "file"+String(r)+".jpg"
                    let parameterName = "image"
                    multipartFormData.append(imgValue, withName:parameterName, fileName:str, mimeType: "image/jpeg")
                
            else
            for (key, value) in params 
                multipartFormData.append(value.data(using: String.Encoding.utf8)!, withName: key )
            

        , to: apiURL,encodingCompletion:  encodingResult in
            switch encodingResult 
            case .success(let upload, _, _):
                upload.responseJSON  response in

                    if let Json = response.result.value as? Dictionary<String,AnyObject> 
                        print(Json)
                        if let responcCode = Json["data"] as?  Dictionary<String,AnyObject>
                            print(responcCode)
                        
                    
                
            case .failure(let encodingError):
                print(encodingError)
            )
        

【讨论】:

【参考方案4】:

你能不能试试这个,它会帮助你。

创建图像字典:-


  let dictimage = NSMutableDictionary()
  dictimage.setValue("pass here Image data", forKey: "pass your image parameter name")

您的其他字段参数,例如

  let dictparam = NSMutableDictionary()
  dictparam.setValue("carex", forKey:"nickname")
  dictparam.setValue("mantap", forKey:"password")

调用这个函数

class func callAPIWithMultiPart(_ url: String,
                                   image:NSDictionary,
                                    param: NSDictionary,
                                    type : HTTPMethod,
                                    controller: UIViewController,
                                    header : [String: String]?,
                                    callSilently : Bool = false,
                                    successBlock: @escaping (_ responseDict: NSDictionary? , _ response: NSArray?) -> Void,
                                    failureBlock: @escaping (_ error: Error? , _ isTimeOut: Bool) -> Void) 


        if isNetworkAvailable() 

            if !callSilently 
                MBProgressHUD.showAdded(to: (UIApplication.shared.delegate?.window!)! , animated: true)
            

            let urlWithUTF8 =  url.addingPercentEncoding(withAllowedCharacters:NSCharacterSet.urlQueryAllowed)

            print("**************************************************")
            print("URL : \(urlWithUTF8!)")
            print("Header : \(String(describing: header))")
            print("Parameter For video : \(video.count)")
            print("Parameter  : \(param)")


            Alamofire.upload(multipartFormData:  (multipartFormData) in

                let arrParametersKey = NSMutableArray(array: param.allKeys)
                let arrParametersValues = NSMutableArray(array: param.allValues)

                //For normal Parameters
                for index in 0 ..< arrParametersKey.count 

                    if let strKey = arrParametersKey.object(at: index) as? String , let strValue = arrParametersValues.object(at: index) as? String 

                        print("********************* MultiPart ******************")
                        print("strKey : \(strKey)")
                        print("strValue : \(strValue)")
                        multipartFormData.append(strValue.data(using: .utf8)!, withName: strKey)
                    
                

                //For File
                if let strFileKeyForWebservices = video.value(forKey: "FileKeyForWebservices") as? String, let strFileName = video.value(forKey: "FileName") as? String, let dataForWebservices = video.value(forKey: "FileData") as? Data, let strFileMineType = video.value(forKey: "FileMineType") as? String 

                    print("********************* MultiPart File ******************")
                    print("FileKeyForWebservices : \(strFileKeyForWebservices)")
                    print("strFileName : \(strFileName)")
                    print("dataForWebservices : \(dataForWebservices.count)")
                    print("strFileMineType : \(strFileMineType)")

                    multipartFormData.append(dataForWebservices, withName: strFileKeyForWebservices, fileName: strFileName, mimeType: strFileMineType)
                


            , usingThreshold: UInt64.init(), to: urlWithUTF8!, method: type, headers: header)  (encodingResult) in

                switch encodingResult 
                case .success(let upload, _, _):

                    if !callSilently 
                        DispatchQueue.main.async 
                            MBProgressHUD.hide(for: ((UIApplication.shared.delegate?.window)!)!, animated: true)
                        
                    

                    upload.responseJSON  response in

                        print("Response : \(String(describing: response.response?.statusCode))");

                        if let aDict = response.result.value as? NSDictionary 
                            successBlock(aDict,nil)
                         else if let aArray = response.result.value as? NSArray 
                            successBlock(nil,aArray)
                         else 
                            failureBlock(nil, true)
                        

                    
                    break
                case .failure(let encodingError):

                    if !callSilently 
                        DispatchQueue.main.async 
                            MBProgressHUD.hide(for: ((UIApplication.shared.delegate?.window)!)!, animated: true)
                        
                    

                    UIAlertController.showAlertWithOkButton(controller, aStrMessage: Localization("alert_SomethingWentWrong") , completion: nil)
                    failureBlock(encodingError, false)
                    break
                

            

         else 
            // Internet is not connected
            UIAlertController.showAlertWithOkButton(controller, aStrMessage: "Internet is not available", completion: nil)
            let aErrorConnection = NSError(domain: "InternetNotAvailable", code: 0456, userInfo: nil)
            failureBlock(aErrorConnection as Error , false)
        

    

如何使用


  self.callAPIWithMultiPart("here apiURL", image: dictimage, param: dictparam, type: .post, controller: controller, header: requestHeader, successBlock: successBlock, failureBlock: failureBlock)

【讨论】:

以上是关于如何将带有表单数据的图像上传到api参数中?的主要内容,如果未能解决你的问题,请参考以下文章

带有 MultiPart 表单数据中的参数的图像上传在 Alamofire 4.0 中不起作用

请求参数为空,在提交带有图像的表单数据 AJAX 后

如何在 Swift 中使用 Alamofire 上传带有 JSON 参数的图像?

带有参数和标题的 Alamofire Multipart-form 图像上传 - Swift

在 SWIFT 中上传带有其他参数的图像

我想使用目标 c 将带有其他参数的图像上传到服务器