How to Upload Image as Binary - ios

I want to upload image as binary, as in Postman we do below
Here is my code
var url = myURLString
url = url.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!
guard let imageData = UIImageJPEGRepresentation(image, 0.4) else {
return
}
request.httpBody = imageData
request.httpMethod = "POST"
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
Alamofire.request(request).responseJSON { (response) in
if let JSON = response.result.value as? NSDictionary {
print(JSON)
} else {
let message = response.result.error != nil ? response.result.error!.localizedDescription : "Unable to communicate."
print(message)
}
}
It seems that request is not attaching image file, returning following error message
"Response could not be serialized, input data was nil or zero length."

For swift 3, Alamofire 4
below code will work fine
var url = myURLString
url = url.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!
guard let imageData = UIImageJPEGRepresentation(image, 0.4) else {
return
}
Alamofire.upload(imageData, to: URL(string: url)!, method: .post, headers: nil).responseJSON { (response) in
if let JSON = response.result.value as? NSDictionary {
print(JSON)
} else {
let message = response.result.error != nil ? response.result.error!.localizedDescription : "Unable to communicate."
print(message)
}
}

I am retrieving image from gallery and taking the name of the image by using below code:
you can use the below function.
func createMultipart(image: UIImage, callback: Bool -> Void){
// use SwiftyJSON to convert a dictionary to JSON
var parameterJSON = JSON([
"id_user": "test"
])
// JSON stringify
let parameterString = parameterJSON.rawString(encoding: NSUTF8StringEncoding, options: nil)
let jsonParameterData = parameterString!.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
// convert image to binary
let imageData = UIImageJPEGRepresentation(image, 0.7)
// upload is part of AlamoFire
upload(
.POST,
URLString: "use your url here",
multipartFormData: { multipartFormData in
// fileData: puts it in "files"
multipartFormData.appendBodyPart(fileData: jsonParameterData!, name: "goesIntoFile", fileName: "json.txt", mimeType: "application/json")
multipartFormData.appendBodyPart(fileData: imageData, name: "file", fileName: "ios.jpg", mimeType: "image/jpg")
// data: puts it in "form"
multipartFormData.appendBodyPart(data: jsonParameterData!, name: "goesIntoForm")
},
encodingCompletion: { encodingResult in
switch encodingResult {
case .Success(let upload, _, _):
upload.responseJSON { request, response, data, error in
let json = JSON(data!)
println("json:: \(json)")
callback(true)
}
case .Failure(let encodingError):
callback(false)
}
}
)
}
let fotoImage = UIImage(named: "foto")
createMultipart(fotoImage!, callback: { success in
if success { }
})

Swift 4 and 5
var urlRequest = URLRequest(url: URL)
urlRequest.httpMethod = "PUT" // POST
urlRequest.setValue("image/jpeg", forHTTPHeaderField: "Content-Type")
var data = image!.jpegData(compressionQuality: CGFloat(0.5))!
URLSession.shared.uploadTask(with: urlRequest, from: data, completionHandler: { responseData, response, error in
DispatchQueue.main.async {
print(response)
guard let responseCode = (response as? HTTPURLResponse)?.statusCode, responseCode == 200 else {
if let error = error {
print(error)
}
return
}
// do your work
}
}).resume()

Related

Uploading image to server using Alamofire put request in swift iOS

I have picked image from image picker and then reduced it's size to below 1 MB and then trying to upload with below function implementation but it was not successful.
Request body schema should be as mentioned in the above image.
please suggest proper way of uploading image with mentioned request body schema.
//Method for uploading image
func uploadImageFile(url:String, imageData: Data, fileName: String, completion: #escaping (Bool) -> Void) {
let headers = configureImageCurrentSession()
AF.upload(
multipartFormData: { multipartFormData in
multipartFormData.append(imageData, withName: fileName)
},
to: url, method: .put , headers: headers)
.response { resp in
print(resp)
print("Data::: \(String(data: resp.data ?? Data(), encoding: .utf8))")
completion(true)
}
}
According to the request body schema need to pass content as object required one how to include that as well in the request.
In completion response it prints as like this.
Data::: Optional("{"statusCode":400,"error":"Bad Request","message":"part content is missing"}")
Check this below code
func imageupload(_ url: String, _ imageData: Data,_ parameters: NSDictionary, completion: #escaping (NSDictionary) -> Void) {
//Set Your URL
guard let url = URL(string: url) else {
return
}
var urlRequest = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 10.0 * 1000)
urlRequest.httpMethod = "PUT"
urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")
urlRequest.addValue("your autho token", forHTTPHeaderField: "Authorization")
// Now Execute
AF.upload(multipartFormData: { multiPart in
for (key, value) in parameters {
if let temp = value as? String {
multiPart.append(temp.data(using: .utf8)!, withName: key as! String)
}
if let temp = value as? Int {
multiPart.append("\(temp)".data(using: .utf8)!, withName: key as! String)
}
if let temp = value as? NSArray {
temp.forEach({ element in
let keyObj = key as! String + "[]"
if let string = element as? String {
multiPart.append(string.data(using: .utf8)!, withName: keyObj)
} else
if let num = element as? Int {
let value = "\(num)"
multiPart.append(value.data(using: .utf8)!, withName: keyObj)
}
})
}
}
multiPart.append(imageData, withName: "image", fileName: "file.png", mimeType: "image/png")
}, with: urlRequest)
.uploadProgress(queue: .main, closure: { progress in
//Current upload progress of file
print("Upload Progress: \(progress.fractionCompleted)")
})
.responseJSON(completionHandler: { data in
print("data = ",data)
switch data.result
{
case .failure(let error):
if let data = data.data {
print("Print Server Error: " + String(data: data, encoding: String.Encoding.utf8)!)
}
print(error)
case .success(let value):
print(value)
}
switch data.result {
case .success(_):
do {
let dictionary = try JSONSerialization.jsonObject(with: data.data!, options: .fragmentsAllowed) as! NSDictionary
print("Success!")
print(dictionary)
}
catch {
// catch error.
print("catch error")
}
break
case .failure(_):
print("failure")
break
}
}).cURLDescription { description in
print(description)
}
}

How to upload image data with some extra parameters to server via POST call using Swift 4.2?

My scenario, I am trying to send some parameters with Image Data to server using POST call. Here, I need to update my code Parameters to Body request, because Image base64 string huge data producing so we cant send long lenth data with it. Please update blow code how to upload image and extra parameters to Server.
apiPath = "https://............com/api/new_line?country=\(get_countryID ?? "unknown")&attachment=\("sample.png")&user_id=\(userid ?? "unknown")"
if let encodeString = apiPath.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed),
let url = URL(string: encodeString) {
let session = URLSession.shared
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.addValue(access_key, forHTTPHeaderField: "access-key")
request.addValue(auth_token!, forHTTPHeaderField: "auth-token")
request.timeoutInterval = 10
let task = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
guard error == nil else {return}
guard let data = data else {return}
do {
//MARK: Create json object from data
if let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String: Any] {
print(json)
// MARK: Validate status code
let status_code : Int = json["status"]! as! Int
let status_message : String = json["message"]! as! String
if (status_code != 200) {
print("ERROR:\(String(describing: status_code))")
DispatchQueue.main.async {
self.showMessageToUser(messageStr: status_message)
}
} else {
DispatchQueue.main.async {
// Show Success Alert View Controller
if self.tfData != "" { // Call Update
self.apistatus(message:Updated Successfully!")
} else {
self.apistatus(message:"Submitted Successfully!")
}
}
}
}
} catch let error {
print(error.localizedDescription)
}
})
task.resume()
}
You can try using Alamofire (https://github.com/Alamofire/Alamofire) as below.
Alamofire.upload(
multipartFormData: { multipartFormData in
multipartFormData.append(photoData, withName: "photoId", fileName: "photoId.png", mimeType: "image/png")
for (key,value) in params { //params is a dictionary of values you wish to upload
multipartFormData.append(value.data(using: .utf8)!, withName: key)
}
},
to: URL(string : urlString)!,
method: .post,
headers: getContentHeader(),
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
if response.response?.statusCode == 200 {
print("Success")
} else {
print("Failure")
}
}
case .failure(let error):
print("Failure")
}
}
)
// Iam use alamofire Method
func sendIMAGeAndParams(urlString:String,imageData:[String:[Data]],header: String,params:[String:AnyObject], success: #escaping (AnyObject) -> Void,failure: #escaping(Error) -> Void) {
let param = ["" : ""]
let url = try! URLRequest.init(url: urlString, method: .post, headers: nil)
Alamofire.upload(multipartFormData: { (formdata) in
for (key, value) in params {
formdata.append("\(value)".data(using: String.Encoding.utf8)!, withName: key)
}
for (key,value) in imageData{
for item in value{
formdata.append(item, withName: key, fileName: "image.jpeg", mimeType: "image/jpeg")
}
}
}, with: url) { (encodingResult) in
switch encodingResult{
case .success(let upload,_,_):
upload.responseJSON(completionHandler: { (response) in
switch response.result{
case .success(_):
if (response.response?.statusCode == 200){
if let value = response.result.value {
success(value as AnyObject)
print(value)
}
}
else{
let value = response.result.value as? [String:Any]
print(value as Any)
}
break
case .failure(let error):
print(error)
break
}
})
break
case .failure(let error):
print(error)
break
}
}
}

No HTTP resource was found that matches the request URI web api using ASP.NET for ios Swift

I need to send POST request to the server and these are the parameters
let params : NSDictionary = ["userid":"\(userID)","sessionid":"\(sessionID)","site_id": "\(siteIDParam)", "latitude":"\(currentlatitude)", "longitude":"\(currentlongitude)", "action": "1", "comments":commentTextView.text ?? ""]
But the problem is I need to send image as byte array and i am using the following code (Swift 3)
func uploadImageRequest(image: UIImage? , urlString: String, imageName : String ,param: [String: AnyObject]? , completion:#escaping(_ success:Bool , _ object : AnyObject?) -> ())
{
let url = NSURL(string: urlString)
let request = NSMutableURLRequest(url: url! as URL)
request.httpMethod = "POST"
let boundary = generateBoundaryString()
//define the multipart request type
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
if (image == nil)
{
return
}
let image_data = UIImageJPEGRepresentation(image!, 0.5)
if(image_data == nil)
{
return
}
let body = NSMutableData()
let fname = "photo.png"
let mimetype = "image/*"
body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Disposition:form-data; name=\"\(imageName)\"; 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)!)
if param != nil {
for (key, value) in param! {
body.append("--\(boundary)\r\n")
body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.append("\(value)\r\n")
}
}
request.httpBody = body as Data
_ = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) -> Void in
if let data = data {
// Json Response
let json = try? JSONSerialization.jsonObject(with: data, options: [])
// response.
if let response = response as? HTTPURLResponse , 200...299 ~= response.statusCode {
completion(true, json as AnyObject?)
} else {
completion(false, json as AnyObject?)
}
} else {
completion(false, error?.localizedDescription as AnyObject?)
}
}.resume()
}
The image is not converted properly I guess so that the response get failed when triggered and I am getting the following error
Message = "No HTTP resource was found that matches the request URI
This API works fine in Android device but it cant be achievied in iOS. I have searched all the links and I couldnt get a proper solution for this. I have also tried using Alamofire but still I got the same error.
You have to set the NSAllowsArbitraryLoads key to YES under NSAppTransportSecurity dictionary in your .plist file.
You can do this easily using alamofire, use the following code to do these things done.
let multipartHeaders = ["Content-Type":"multipart/form-data"]
let paramString: String = "parameters in json string..."
Alamofire.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append(paramString.data(using: .utf8)!, withName: "json")
multipartFormData.append(<imageDataHere>, withName: "myimage", fileName: "myImage.jpeg", mimeType: "image
jpeg")
}, usingThreshold: SessionManager.multipartFormDataEncodingMemoryThreshold, to: url, method: .post, headers:
multipartHeader) { (encodingResult) in
switch encodingResult {
case .success(let request, _, _):
request.responseJSON(completionHandler: { (response) in
print(response)
})
case .failure(let error):
print(error.localizedDescription)
}
}
This piece of code helped me solve my problem. I just send my image as a file and remaining parameters as a string without appending it to my multipart body.
let imageData = UIImageJPEGRepresentation(userImage, 0.2)!
let docDir = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let imageURL = docDir.appendingPathComponent("tmp.jpg")
try! imageData.write(to: imageURL)
let multipartHeaders = ["Content-Type":"multipart/form-data"]
let paramString: String = "userid=\(userId)&action=1"
Alamofire.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append(imageURL, withName: "profilepic")
}, usingThreshold: SessionManager.multipartFormDataEncodingMemoryThreshold, to: URL(string: ATTENDANCE_URL+paramString)!, method: .post, headers:
multipartHeaders) { (encodingResult) in
switch encodingResult {
case .success(let request, _, _):
request.responseJSON(completionHandler: { (response) in
print(response.result.value)
let value = response.result.value as! [String: Any]
})
case .failure(let error):
print(error.localizedDescription)
}
}

Alamofire file upload getting error "JSON text did not start with array or object and option to allow fragments not set"

Below is my code referring this question answer
func createRequest(ResumeID: String, CandidateID: String, MediaName: String, FileExtension : String, MediaType : String) throws -> URLRequest {
let parameters = NSDictionary(objects: [ResumeID, CandidateID, MediaName, FileExtension,MediaType], forKeys: ["ResumeID" as NSCopying, "CandidateID" as NSCopying, "MediaName" as NSCopying, "FileExtension" as NSCopying, "MediaType" as NSCopying])
let boundary = generateBoundaryString()
let url = URL(string: "http://192.168.1.29/ColorsKit_New_Svr/WTCSvr.svc/WTCService?Id=6&SPName=Usp_RTN_IU_CandidateSubmissionResume")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let path1 = Bundle.main.path(forResource: "dummy-pdf_2", ofType: "pdf")!
request.httpBody = try createBody(with: parameters as? [String : String], filePathKey: "MediaContent", paths: [path1], boundary: boundary)
return request
}
private func createBody(with parameters: [String: String]?, filePathKey: String, paths: [String], boundary: String) throws -> Data {
var body = Data()
if parameters != nil {
for (key, value) in parameters! {
body.append("--\(boundary)\r\n")
body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.append("\(value)\r\n")
}
}
for path in paths {
let url = URL(fileURLWithPath: path)
let filename = url.lastPathComponent
let data = try Data(contentsOf: url)
let mimetype = mimeType(for: path)
body.append("--\(boundary)\r\n")
body.append("Content-Disposition: form-data; name=\"\(filePathKey)\"; filename=\"\(filename)\"\r\n")
body.append("Content-Type: \(mimetype)\r\n\r\n")
body.append(data)
body.append("\r\n")
}
body.append("--\(boundary)--\r\n")
return body
}
func sendMultipartRequest() {
let request: URLRequest
do {
request = try createRequest(ResumeID: "1", CandidateID: "1241124", MediaName: "dummy-pdf", FileExtension: "pdf", MediaType: "pdf")
} catch {
print(error)
return
}
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard error == nil else {
// handle error here
print(error!)
return
}
// if response was JSON, then parse it
do {
let responseDictionary = try JSONSerialization.jsonObject(with: data!)
print("success == \(responseDictionary)")
// note, if you want to update the UI, make sure to dispatch that to the main queue, e.g.:
//
// DispatchQueue.main.async {
// // update your UI and model objects here
// }
} catch {
print(error)
let responseString = String(data: data!, encoding: .utf8)
print("responseString = \(String(describing: responseString))")
}
}
task.resume()
}
The Response I'm getting is:
Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start
with array or object and option to allow fragments not set."
UserInfo={NSDebugDescription=JSON text did not start with array or
object and option to allow fragments not set.} responseString =
Optional("No Records Found")
This is strange because Postman is giving correct response. Means there is something missing in the code only :(
Use Alamofire
let upload_url = "your url"
let fieldName = "UploadedFile"
let mimeType = "plain/text"
Alamofire.upload(multipartFormData: { multipartFormData in
//you can add multiple file
multipartFormData.append(fileData as Data, withName: fieldName, fileName: fileName, mimeType: mimeType)
}, to: upload_url, method: .post, headers: ["Authorization": "auth_token"],
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.response { [weak self] response in
guard let _ = self else {
return
}
debugPrint(response)
}
case .failure(let encodingError):
debugPrint("uploaderService error:\(encodingError)")
}
})
Use JSONSerialization as below
if let responseDictionary = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? String {
...
}

How to send an image as POST in web service swift

var urlString = ""
let url = NSURL(string: urlString)
let theRequest = NSMutableURLRequest(URL: url!)
theRequest.HTTPMethod = "POST"
let parameters = []
var err:NSError!
do{
theRequest.HTTPBody = try NSJSONSerialization.dataWithJSONObject(parameters, options: [])
}
catch let error as NSError{
err = error
theRequest.HTTPBody = nil
}
theRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
theRequest.addValue("application/json", forHTTPHeaderField: "Accept")
Here I am using a 3rd party class library for a signature . How can I POST it to webservices in the form an image?
Simple example for you:
//create session
var urlSession : NSURLSession!
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
urlSession = NSURLSession(configuration: configuration)
func updateUserDetails(image : UIImage? , dictUserDetails: [String: String?] ,completionClosure: (repos :NSDictionary) ->()) {
let request = NSMutableURLRequest(URL: NSURL(string:"Your URL" )!)
request.HTTPMethod = "POST"
let boundary = generateBoundaryString()
let token = getUserToken() as String
request.addValue("Token " + token, forHTTPHeaderField: "Authorization") // add token if you need
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
guard image != nil else {
request.HTTPBody = createBodyWithParameters(dictUserDetails, filePathKey: "profile_pic", imageDataKey: nil, boundary: boundary)
let postDataTask = self.urlSession.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if (error != nil) {
print(error!.localizedDescription)
}
if (data != nil) {
if let jsonResult: NSDictionary = (try? NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)) as? NSDictionary
{
completionClosure(repos: jsonResult)
}
else
{
completionClosure(repos: NSDictionary())
}
} else {
completionClosure(repos: NSDictionary())
}
})
postDataTask.resume()
return
}
let imageData = UIImageJPEGRepresentation(image!, 0.3)
request.HTTPBody = createBodyWithParameters(dictUserDetails, filePathKey: "profile_pic", imageDataKey: imageData, boundary: boundary)
let postDataTask = self.urlSession.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
if (error != nil) {
print(error!.localizedDescription)
}
if (data != nil) {
if let jsonResult: NSDictionary = (try? NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)) as? NSDictionary
{
completionClosure(repos: jsonResult)
}
else
{
completionClosure(repos: NSDictionary())
}
} else {
completionClosure(repos: NSDictionary())
}
})
postDataTask.resume()
}
Helper Functions:
//Generate boundary
func generateBoundaryString() -> String {
return "Boundary-\(NSUUID().UUIDString)"
}
//create body
func createBodyWithParameters(parameters: [String: String?]?, filePathKey: String?, imageDataKey: NSData?, boundary: String) -> NSData {
let body = NSMutableData()
if parameters != nil {
for (key, value) in parameters! {
if value != nil {
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.appendString("\(value!)\r\n")
}
}
}
if imageDataKey != nil
{
let filename = "user-profile.jpg"
let mimetype = "image/jpg"
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
body.appendString("Content-Type: \(mimetype)\r\n\r\n")
body.appendData(imageDataKey!)
body.appendString("\r\n")
body.appendString("--\(boundary)--\r\n")
}
return body
}
Now you can use it this way:
updateUserDetails(yourImage, dictUserDetails: [
//parameters example
"date_of_birth": birthDate,
"first_name": firstName,
"last_name" : lastName,
"email" : email,
"phone_number" : phoneNumber,
"address" : address,
"martial_status" : userMaritialStatus
], completionClosure: { (repos) -> () in
print(repos)
})
Hope it will help.
You did not say which third party library you are using, so you can use Alamofire for it, using this code:
Alamofire.upload(
.POST,
"your_API_URL_here",
multipartFormData: { multipartFormData in
if let _ = image {
if let imageData = UIImageJPEGRepresentation(image!, 1.0) {
multipartFormData.appendBodyPart(data: imageData, name: "file", fileName: "file.jpeg", mimeType: "image/jpeg")
} else {
print(image)
}
}
}, encodingCompletion: {
encodingResult in
switch encodingResult {
case .Success(let upload, _, _):
upload.responseJSON { response in
switch response.result {
case .Success:
print("Success")
case .Failure(let error):
print(error)
}
}
case .Failure(let encodingError):
print(encodingError)
}
}
)
}
} catch _ {
}

Resources