0

I want to send an image from gallery to server in an API call. This image has to be passed as a parameter. To pass the image as a parameter, I tried to get the url of the image like so but it wasn't giving the correct url..

var selectedImage : UIImage = image
let imageData: NSData = UIImagePNGRepresentation(selectedImage)! as NSData
let imageStr = imageData.base64EncodedString(options:.endLineWithCarriageReturn)
imageArray.append(image)

Also I tried to upload the image like so...

        for img in imageArray {

            let url = "http://myApp..com/a/images_upload"
            let headers = [ "Content-Type":"application/x-www-form-urlencoded"]

            let URL = try! URLRequest(url: url, method: .post, headers: headers)
            let parameters =
                [
                    "access_token": accessToken
                    "image": img
                    ] as [String : Any]


            let imgData = UIImageJPEGRepresentation(img, 0.2)!

            Alamofire.upload(multipartFormData: { (multipartFormData) in
                multipartFormData.append(imgData, withName: "image",fileName: "file.jpg", mimeType: "file")
                for (key, value) in parameters {
                    multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
                }
            }, with: URL) { (result) in
                switch result {
                case .success(let upload, _, _):

                    upload.uploadProgress(closure: { (progress) in
                        print("Upload Progress: \(progress.fractionCompleted)")
                    })

                    upload.responseJSON { response in
                        print(response.result.value)
                        if let value = response.result.value {                                
                            print("IMG UPLOADED!!!")
                        }
                    }
                    case .failure(let encodingError):
                    print(“ERROR”)
}}}

But this is also crashing. I've been having this issue for quite some time now...not able to figure out what the exact solution is...Hope someone can help...:) Also did go through a lot of similar questions on SO. But couldn't find a solution till...

EDIT: My parameters are:

let Parameters =
                    [
                        "access_token": commonVarForAccessToken,
                        "seller_id": idForNewOldUser, 
                        "product_id": self.productId,
                        "is_default": "1",
                        "sequence": 1,
                        "image": self.localPath
                        ] as [String : Any]
  • https://stackoverflow.com/questions/39631823/swift-3-alamofilre-4-0-multipart-image-upload-with-progress and https://stackoverflow.com/questions/39809867/alamofire-4-upload-with-parameters – iPatel Oct 09 '17 at 08:58
  • did go through that before, @iPatel...But it wasn't of help... –  Oct 09 '17 at 08:59
  • use my answer https://stackoverflow.com/questions/45651187/upload-photo-file-with-json-and-custom-headers-via-swift-3-and-alamofire-4-i/46116478#46116478 Just pass your image in dictionary with key – Jitendra Modi Oct 09 '17 at 09:00
  • I'm confused if it can be used in my scenario...?what is your opinion, @JitendraModi ? –  Oct 09 '17 at 09:03
  • It is very easy to implement, Just declare a class of above and below is the use of that class. – Jitendra Modi Oct 09 '17 at 09:05
  • Rename your `var`s `URL` and `Parameters` to lower case, now it's confusing you and everyone. – Au Ris Oct 09 '17 at 09:08
  • Theres a url already in lowercase so gave the other url in caps.. have changed the parameters to lowercase btw if it was confusing...:) –  Oct 09 '17 at 09:13
  • Bit confused regarding where to use your class, @ JitendraModi..also what is self.webservice... ? –  Oct 09 '17 at 09:22
  • Can you at least show us the crash logs? – John Russel Usi Oct 09 '17 at 09:32
  • The crash tells something like...Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_SwiftTypePreservingNSNumber dataUsingEncoding:]: unrecognized selector sent to instance 0x608 –  Oct 09 '17 at 09:40

2 Answers2

0

First use this Function for making URLRequest.

 func makeUrlRequestWithComponents(urlString:String, parameters:Dictionary<String, Any>, imageData:NSData) -> (URLRequestConvertible, NSData) {

// create url request to send
let mutableURLRequest = NSMutableURLRequest(URL: NSURL(string: urlString)!)
mutableURLRequest.HTTPMethod = Alamofire.Method.POST.rawValue
let boundaryConstant = "myRandomBoundary12345";
let contentType = "multipart/form-data;boundary="+boundaryConstant
mutableURLRequest.setValue(contentType, forHTTPHeaderField: "Content-Type")



// create upload data to send
let uploadData = NSMutableData()

// add image
uploadData.appendData("\r\n--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
uploadData.appendData("Content-Disposition: form-data; name=\"file\"; filename=\"file.png\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
uploadData.appendData("Content-Type: image/png\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
uploadData.appendData(imageData)

// add parameters
for (key, value) in parameters {
    uploadData.appendData("\r\n--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
    uploadData.appendData("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n\(value)".dataUsingEncoding(NSUTF8StringEncoding)!)
}
uploadData.appendData("\r\n--\(boundaryConstant)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)



// return URLRequestConvertible and NSData
return (Alamofire.ParameterEncoding.URL.encode(mutableURLRequest, parameters: nil).0, uploadData)
 }

And then this is the function to upload Image.

func uploadImage()
{

    let Parameters =
   [
"access_token": commonVarForAccessToken,
"seller_id": idForNewOldUser,
"product_id": self.productId,
"is_default": "1",
"sequence": 1,
] as [String : Any]


// example image data

let imageData = UIImagePNGRepresentation(myImageView.image!,1)



// CREATE AND SEND REQUEST ----------

 let urlRequest = makeUrlRequestWithComponents("http://myApp..com/a/images_upload", parameters:      parameters, imageData: imageData)

  Alamofire.upload(urlRequest.0, urlRequest.1).progress { (bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) in
    println("\(totalBytesWritten) / \(totalBytesExpectedToWrite)")
}
.responseJSON { (request, response, JSON, error) in
    println("REQUEST \(request)")
    println("RESPONSE \(response)")
    println("JSON \(JSON)")
    println("ERROR \(error)")
  }
 }
Zee
  • 327
  • 1
  • 8
  • Thanks @Zee, but I pick the image from the gallery. So should that image not be converted to its url first...? –  Oct 09 '17 at 09:32
  • You can pick image from gallery and assign it to UIImageView and then use it in that function – Zee Oct 09 '17 at 09:48
  • also, you have given a proper filename of the image that is to be uploaded like so...imageFileName.jpg. But if I pick an image from gallery then that image won't have such a definite name. So what are we to do in such a case...? –  Oct 09 '17 at 09:52
  • this is optional and this is not my image file nam. – Zee Oct 09 '17 at 09:54
  • variable named (data) will define every thing – Zee Oct 09 '17 at 09:55
  • Ok..so you are saying that..name: "image_1", and fileName: "imageFileName.jpg" can be ommitted..? –  Oct 09 '17 at 09:59
  • OK..and one more thing ...this function is called on any action we require right...? –  Oct 09 '17 at 10:03
  • the apiToken that you have mentioned is the parameter right...? –  Oct 09 '17 at 10:21
  • but i have actually not one but about 5 different parameters..so where can those be mentioned...? –  Oct 09 '17 at 10:29
  • please mention names of your 5 parameters. – Zee Oct 09 '17 at 10:32
  • I have edited the question and added the parameters. But in the last parameter ‘image’ I’m supposed to mention the image path. So considering your solution, what can we give in its place…? –  Oct 09 '17 at 10:36
  • Ok..but where will the function makeUrlRequestWithComponents be called...? –  Oct 09 '17 at 11:12
  • in uploadImage() function – Zee Oct 09 '17 at 11:19
0

Almofire With Image:-

Alamofire.upload(multipartFormData: { (multipartFormData) in
            print(parameters)
            if Array(parameters.keys).contains(Keys.Image) {
            multipartFormData.append(UIImageJPEGRepresentation((parameters)[Keys.Image] as! UIImage, 1)!, withName: "image", fileName: "swift_file.jpeg", mimeType: "image/jpeg")
            }
            for (key, value) in parameters {
                print(key,value)
                if key != Keys.Image{
                multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
                }
            }
        }, to:url)
        { (result) in
            switch result {
            case .success(let upload, _, _):
                upload.uploadProgress(closure: { (progress) in
                    //Print progress
                })
                upload.responseJSON { response in
                    print(response.result)
                    self.getValidDict(result: response.result, completion: { (dict, error) in
                        var dict = dict
                        print(dict!)
                        print(parameters)
                        if dict == nil {
                            dict = NSDictionary.init(dictionary:
                                [kResultMessageKey: error?.localizedDescription ?? "Some error has been occured",
                                 kResultStatusKey: false])
                        }
                           Completion(true,dict![Keys.result]! as AnyObject)
                    })
               }
            case .failure(let encodingError):
                //print(encodingError.description)
                Completion(false,encodingError.localizedDescription as AnyObject)
                break
            }
        }
Vakas
  • 6,291
  • 3
  • 35
  • 47