Data fetched from server using
var request = var request = URLRequest(url: URL(string: "http://www.example.com/test.php")!)
request.httpMethod = "POST"
let akey:String = txt_key.stringValue;
let email:String = txt_email.stringValue
let VAL:String="test"
var data="blah"
let postString = data
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else { /
print("error=\(error)")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { /
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
}
let responseString = String(data: data, encoding: .utf8)
print(responseString)
}
task.resume()
Decryption using
func aesDecrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.data(using: String.Encoding.utf8),
let data = NSData(base64Encoded: self, options: .ignoreUnknownCharacters),
let cryptData = NSMutableData(length: Int((data.length)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCDecrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
(keyData as NSData).bytes, keyLength,
iv,
data.bytes, data.length,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let unencryptedMessage = String(data: cryptData as Data, encoding:String.Encoding.utf8)
return unencryptedMessage
}
else {
return nil
}
}
return nil
}
Even when responseString is not null,The following code always returns
optional("")
let unencode = String(describing: responseString!).aesDecrypt(key: "123456789012asdsadasd", iv: "iv-salt-string--")
Why is this happening ? Please advice.
Per MartinR's comment:
I have verified that "JDoNBXk21oJ9x15Bkv12uw==" is exactly the result of encrypting an empty string with your key and iv. The error is in your PHP script, not in the Swift code.
Therefore you need to resolve the error on the server.
Related
I have encrypt and decrypt method , encrypt method working fine tested with c# encrypt and decrypt method, in android also working fine but in swift decrypt method not working its show me null i try many times but not success , anyone help me regarding solve this problem highly appreciate because. i'm new in swift
PlainString = "5lg3yg7Q+Y8="
func tripleDesDecrypt(PlainString :String) -> String? {
let md5Data = "FIFEDCBA98765432104AABFD"
if let keyData = md5Data.data(using: String.Encoding.utf8),
let data = PlainString.data(using: .utf8),
let cryptData = NSMutableData(length: Int(data.count) + kCCBlockSize3DES) {
let keyLength = size_t(kCCKeySize3DES)
let operation: CCOperation = UInt32(kCCDecrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES)
let options: CCOptions = UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
(keyData as NSData).bytes, keyLength,
nil,
data.bytes, data.count,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let unencryptedMessage = String(data: cryptData as Data, encoding:String.Encoding.utf8)
return unencryptedMessage
}
else {
return nil
}
}
return nil
}
func tripleDesEncrypt(PlainString: String) -> String{
let md5Data = "FIFEDCBA98765432104AABFD"
// let md5Data = MD5(string:keyvalue)
let PlainStringvar = PlainString
guard let data = PlainStringvar.data(using: .utf8) else {
return ""
}
let cryptData = NSMutableData(length: Int(data.count) + kCCBlockSize3DES)!
let keyLength = size_t(kCCKeySize3DES)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES)
let options: CCOptions = UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
md5Data.bytes, keyLength,
nil,
data.bytes, data.count,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
var base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
return base64cryptString//// encodeString(str: base64cryptString)
} else {
print("Error: \(cryptStatus)")
}
return ""
}
You have the data and cryptData parameters the wrong way around in your decrypt function. The dataIn values ie crypted data are first and then the dataOut values follow ie decrypted data. It should be as follows
let cryptStatus = CCCrypt(operation,
algoritm,
options,
(keyData as NSData).bytes, keyLength,
nil,
cryptData.bytes, cryptData.length,
data.mutableBytes, data.count,
&numBytesEncrypted)
I have the following method that I want to decrypt. The following method Encrypts. What should I do to decrypt?
Code
PlainString = "5lg3yg7Q+Y8="
func tripleDesEncrypt(PlainString: String) -> String {
let keyData = "FIFEDCBA98765432104AABFD"
let PlainStringvar = PlainString
guard let data = PlainStringvar.data(using: .utf8) else {
return ""
}
let cryptData = NSMutableData(length: Int(data.count) + kCCBlockSize3DES)!
let keyLength = size_t(kCCKeySize3DES)
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES)
let options: CCOptions = UInt32(kCCOptionECBMode + kCCOptionPKCS7Padding)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
keyData.bytes, keyLength,
nil,
data.bytes, data.count,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
var base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
return base64cryptString //// encodeString(str: base64cryptString)
} else {
print("Error: \(cryptStatus)")
}
return ""
}
I never did encrypt/decrypt on Swift but based on that code you just need to change this line
let operation: CCOperation = UInt32(kCCEncrypt)
to
let operation: CCOperation = UInt32(kCCDecrypt)
While making a small search for this answer I came across this
https://github.com/DigitalLeaves/CommonCrypto-in-Swift
It might be useful, not only as a library that you can use, but to study code and also looks that you're new to the Swift language so I advise you to take a look
Your tripleDesEncrypt does not compile in Swift 4, so I needed to fix it:
func tripleDesEncrypt(plainString: String) -> String {
let keyData = "FIFEDCBA98765432104AABFD".data(using: .utf8)!
//Converting plainString to UTF-8 encoded data
guard let data = plainString.data(using: .utf8) else {
return ""
}
var cryptData = Data(count: data.count + kCCBlockSize3DES)
let keyLength = size_t(kCCKeySize3DES)
let operation: CCOperation = CCOperation(kCCEncrypt)
let algoritm: CCAlgorithm = CCAlgorithm(kCCAlgorithm3DES)
let options: CCOptions = CCOptions(kCCOptionECBMode + kCCOptionPKCS7Padding)
var numBytesEncrypted :size_t = 0
//Encrypting UTF-8 encoded data in 3DES, ECB, PKCS7 with keyData
let cryptStatus = keyData.withUnsafeBytes {keyBytes in
data.withUnsafeBytes {dataBytes in
cryptData.withUnsafeMutableBytes {mutableBytes in
CCCrypt(operation,
algoritm,
options,
keyBytes, keyLength,
nil,
dataBytes, data.count,
mutableBytes, cryptData.count,
&numBytesEncrypted)
}
}
}
if cryptStatus == CCCryptorStatus(kCCSuccess) {
//Converting encrypted data into base-64 String
cryptData.count = Int(numBytesEncrypted)
let base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
return base64cryptString
} else {
print("Error: \(cryptStatus)")
return ""
}
}
The code is made of 3 parts:
Converting plainString to UTF-8 encoded data
Encrypting UTF-8 encoded data in 3DES, ECB, PKCS7 with keyData
Converting encrypted data into base-64 String
So, to decrypt, you need to apply inverse conversion in reversed order:
Converting base-64 String into encrypted data
Decrypting to UTF-8 encoded data in 3DES, ECB, PKCS7 with keyData
Converting UTF-8 encoded data into plainString
The method looks like this:
func tripleDesDecrypt(base64String: String) -> String {
let keyData = "FIFEDCBA98765432104AABFD".data(using: .utf8)!
//Converting base-64 String into encrypted data
guard let encryptedData = Data(base64Encoded: base64String, options: .ignoreUnknownCharacters) else {
return ""
}
var decryptedData = Data(count: encryptedData.count)
let keyLength = size_t(kCCKeySize3DES)
let operation: CCOperation = CCOperation(kCCDecrypt)
let algoritm: CCAlgorithm = CCAlgorithm(kCCAlgorithm3DES)
let options: CCOptions = CCOptions(kCCOptionECBMode + kCCOptionPKCS7Padding)
var numBytesDecrypted :size_t = 0
//Decrypting to UTF-8 encoded data in 3DES, ECB, PKCS7 with keyData
let cryptStatus = keyData.withUnsafeBytes {keyBytes in
encryptedData.withUnsafeBytes {dataBytes in
decryptedData.withUnsafeMutableBytes {mutableBytes in
CCCrypt(operation,
algoritm,
options,
keyBytes, keyLength,
nil,
dataBytes, encryptedData.count,
mutableBytes, decryptedData.count,
&numBytesDecrypted)
}
}
}
if cryptStatus == CCCryptorStatus(kCCSuccess) {
//Converting UTF-8 encoded data into plainString
let plainString = String(data: decryptedData, encoding: .utf8) ?? ""
return plainString
} else {
print("Error: \(cryptStatus)")
return ""
}
}
Usage:
let encryptedString = tripleDesEncrypt(plainString: "This is a test.")
print(encryptedString) //->QmWafUwPY/MVWu3lHa3c5A==
let decryptedString = tripleDesDecrypt(base64String: encryptedString)
print(decryptedString) //->This is a test.
//Try by yourself...
let origString = tripleDesDecrypt(base64String: "5lg3yg7Q+Y8=")
print(origString)
Anybody have an idea how to configure HTTP Headers with NSURLRequest in Swift? I have authentication set up on my server and it only needs a token passed to it but I'm having trouble setting the header
my code:
func getLatestData() {
var loggedInUsersNumber:String = SharingManager.sharedInstance.userID
var usersDataPoint:String = StormDataPoint + loggedInUsersNumber
activityIND.hidden = false
activityIND.startAnimating()
let request = NSURLRequest(URL: NSURL(string: usersDataPoint)!)
let tokenString = SharingManager.sharedInstance.authToken
//request.setValue("Token " + tokenString, forKey: "Authorization")
let urlSession = NSURLSession.sharedSession()
let task = urlSession.dataTaskWithRequest(request, completionHandler: {
(data, response, error) -> Void in
if let error = error {
print(error)
return }
I created a property "tokenString" to be the token to pass into the header and on the next line where i commented it out. request.setvalue - I popped it in and get an error to the tune of "cannot override data type". All my searches show Objective C help. Is there a better way to try to pass a header in?
In Swift 3, use the URLRequest structure instead of NSURLRequest (similarly, NSURL ↦ URL, NSURLSession ↦ URLSession, etc.).
Then use addValue(_:forHTTPHeaderField:) to add a header.
// swift 3:
var request = URLRequest(url: URL(string: usersDataPoint)!)
request.addValue("Token \(tokenString)", forHTTPHeaderField: "Authorization")
In Swift 2.2, you use an NSMutableURLRequest if you need to modify it.
// swift 2:
let request = NSMutableURLRequest(URL: NSURL(string: usersDataPoint)!)
request.addValue("Token \(tokenString)", forHTTPHeaderField: "Authorization")
You can create Mutable URL Request, then set value for field name.
let request = NSMutableURLRequest(URL: NSURL(string: yourURLString)!)
request.setValue("\(yourValue)", forHTTPHeaderField: "Header-field-name")
Swift3 bigger example
var req: URLRequest = /* create requets */
req.setValue("Bearer Y3GzLG2x6wSXihmUGhwGFw", forHTTPHeaderField: "Authorization")
req.timeoutInterval = 10
let task = URLSession.shared.dataTask(with: req, completionHandler: { (data, response, error) in
print("completionHandler invoked")
})
task.resume()
private func getHeaderData(url:String) -> Dictionary<String, String> {
let strLanguage:String = LanguageManager.sharedInstance.getCurrentLanuage()
let params:[String:String] = [WSKeys.XAPIkey: XAPIKeyString,
WSKeys.language:strLanguage
]
return params
}
class NetworkManager: NSObject {
static let shared = NetworkManager()
//MARK: - WS CALLS Methods
func GETRequset(showLoader: Bool, url:String, success:#escaping (AnyObject!) -> Void, failed:#escaping (AnyObject!) -> Void) {
self.startProgressLoading(isStart: showLoader)
var request = URLRequest(url: URL(string: url)!)
request.httpMethod = "GET"
request.allHTTPHeaderFields = getHeaderData(url: url)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
print("O/P error=\(error.debugDescription)")
self.stopProgressLoading()
failed(error.debugDescription as AnyObject!)
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
self.stopProgressLoading()
failed(response as AnyObject!)
}
let responseString = String(data: data, encoding: .utf8)
self.stopProgressLoading()
DispatchQueue.main.async {
success(responseString as AnyObject!)
}
}
task.resume()
}
func POSTRequset(showLoader: Bool, url:String, parameter:[String : AnyObject]?, success:#escaping (AnyObject!) -> Void, failed:#escaping (AnyObject!) -> Void) {
self.startProgressLoading(isStart: showLoader)
let boundary = "Boundary-\(NSUUID().uuidString)"
let url = URL(string: url)
let request = NSMutableURLRequest(url: url!)
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let headerData = getHeaderData(url: (url?.absoluteString)!)
request.allHTTPHeaderFields = headerData
var body = Data()
if parameter != nil {
for (key, value) in parameter! {
body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: String.Encoding.utf8)!)
body.append("\(value)\r\n".data(using: String.Encoding.utf8)!)
}
}
body.append("--\(boundary)--\r\n".data(using: String.Encoding.utf8)!)
request.httpBody = body
let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: {
data, response, error in
print("##############################################################################")
guard let data = data, error == nil else {
failed(error.debugDescription as AnyObject!)
self.stopProgressLoading()
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
self.stopProgressLoading()
failed(response as AnyObject!)
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode == 401 {
self.stopProgressLoading()
failed(response as AnyObject!)
}
let responseString = String(data: data, encoding: .utf8)
let dict = self.convertToDictionary(text: responseString!)
if dict != nil
{
print("O/P responseDict = \(String(describing: dict))")
}
else
{
print("O/P responseString = \(String(describing: responseString))")
}
print("##############################################################################")
if (dict?["status"]) != nil {
let strStatus = dict?[WSKeys.status] as! NSNumber
let strMessage = dict?[WSKeys.message] as! NSString
self.stopProgressLoading()
if strStatus == 401{
failed(strMessage)
DispatchQueue.main.async {
getDelegate().logOut()
}
} else {
DispatchQueue.main.async {
success(dict as AnyObject!)
}
}
}
})
task.resume()
}
func POSTJsonArrayRequset(showLoader: Bool, url:String, parameter:[String : AnyObject]?, success:#escaping (AnyObject!) -> Void, failed:#escaping (AnyObject!) -> Void) {
self.startProgressLoading(isStart: showLoader)
let request = NSMutableURLRequest(url: URL(string:url)!)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try! JSONSerialization.data(withJSONObject: parameter)
request.httpMethod = "POST"
let headerData = getHeaderData(url: url)
request.allHTTPHeaderFields = headerData
let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: {
data, response, error in
print("##############################################################################")
print("URL: \(String(describing: url))")
print("PARAMS: \(String(describing: parameter))")
print("Headers: \(headerData)")
print("Method: Post")
guard let data = data, error == nil else {
print("O/P error=\(error.debugDescription)")
failed(error.debugDescription as AnyObject!)
self.stopProgressLoading()
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
print("O/P statusCode should be 200, but is \(httpStatus.statusCode)")
// print("O/P response = \(String(describing: response))")
self.stopProgressLoading()
failed(response as AnyObject!)
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode == 401 {
print("O/P statusCode should be 401, but is \(httpStatus.statusCode)")
// print("O/P response = \(String(describing: response))")
self.stopProgressLoading()
failed(response as AnyObject!)
}
let responseString = String(data: data, encoding: .utf8)
let dict = self.convertToDictionary(text: responseString!)
if dict != nil
{
print("O/P responseDict = \(String(describing: dict))")
}
else
{
print("O/P responseString = \(String(describing: responseString))")
}
print("##############################################################################")
let strStatus = dict?[WSKeys.status] as! NSNumber
let strMessage = dict?[WSKeys.message] as! NSString
self.stopProgressLoading()
if strStatus == 401{
failed(strMessage)
DispatchQueue.main.async {
getDelegate().logOut()
}
} else {
DispatchQueue.main.async {
success(dict as AnyObject!)
}
}
})
task.resume()
}
func POSTJsonArrayRequsetTap(showLoader: Bool, url:String, parameter:[String : AnyObject]?, success:#escaping (AnyObject!) -> Void, failed:#escaping (AnyObject!) -> Void) {
self.startProgressLoading(isStart: showLoader)
let request = NSMutableURLRequest(url: URL(string:url)!)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try! JSONSerialization.data(withJSONObject: parameter)
request.httpMethod = "POST"
let headerData = ["content-type": "application/json"]
request.allHTTPHeaderFields = headerData
let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: {
data, response, error in
print("##############################################################################")
print("URL: \(String(describing: url))")
print("PARAMS: \(String(describing: parameter))")
print("Headers: \(headerData)")
print("Method: Post")
guard let data = data, error == nil else {
print("O/P error=\(error.debugDescription)")
failed(error.debugDescription as AnyObject!)
self.stopProgressLoading()
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
print("O/P statusCode should be 200, but is \(httpStatus.statusCode)")
// print("O/P response = \(String(describing: response))")
self.stopProgressLoading()
failed(response as AnyObject!)
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode == 401 {
print("O/P statusCode should be 401, but is \(httpStatus.statusCode)")
// print("O/P response = \(String(describing: response))")
self.stopProgressLoading()
failed(response as AnyObject!)
}
let responseString = String(data: data, encoding: .utf8)
let dict = self.convertToDictionary(text: responseString!)
if dict != nil
{
print("O/P responseDict = \(String(describing: dict))")
}
else
{
print("O/P responseString = \(String(describing: responseString))")
}
print("##############################################################################")
let strStatus = dict?[WSKeys.status] as! NSNumber
let strMessage = dict?[WSKeys.message] as! NSString
self.stopProgressLoading()
if strStatus == 401{
failed(strMessage)
DispatchQueue.main.async {
getDelegate().logOut()
}
} else {
DispatchQueue.main.async {
success(dict as AnyObject!)
}
}
})
task.resume()
}
func convertToDictionary(text: String) -> [String: Any]? {
if let data = text.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
} catch {
print(error.localizedDescription)
}
}
return nil
}
func MultipartFormDataRequset(showLoader: Bool, urlString:String, mediaKey:String?, mediaDataArray:[Dictionary<String, AnyObject>]?, parameter:[String : AnyObject]?, success:#escaping (AnyObject!) -> Void, failed:#escaping (AnyObject!) -> Void) {
let boundary = "Boundary-\(NSUUID().uuidString)"
let url = URL(string: urlString)
let request = NSMutableURLRequest(url: url!)
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.allHTTPHeaderFields = getHeaderData(url: urlString)
var body = Data()
if parameter != nil {
for (key, value) in parameter! {
body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: String.Encoding.utf8)!)
body.append("\(value)\r\n".data(using: String.Encoding.utf8)!)
}
}
if mediaDataArray != nil {
var i = 0
for var dict in mediaDataArray! {
let data = dict["data"]
let mimetype = "application/octet-stream"
body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
let key = "\(String(describing: mediaKey))[\(i)]"
body.append("Content-Disposition: form-data; name=\"\(key)\"; filename=\"\(dict["fileName"]!)\"\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Type: \(mimetype)\r\n\r\n".data(using: String.Encoding.utf8)!)
body.append(data! as! Data)
body.append("\r\n".data(using: String.Encoding.utf8)!)
i = i + 1
}
}
body.append("--\(boundary)--\r\n".data(using: String.Encoding.utf8)!)
request.httpBody = body
let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: {
data, response, error in
guard let data = data, error == nil else {
print("O/P error=\(error.debugDescription)")
failed(error.debugDescription as AnyObject!)
self.stopProgressLoading()
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
print("O/P statusCode should be 200, but is \(httpStatus.statusCode)")
print("O/P response = \(String(describing: response))")
self.stopProgressLoading()
failed(response as AnyObject!)
}
let responseString = String(data: data, encoding: .utf8)
print("O/P responseString = \(String(describing: responseString))")
self.stopProgressLoading()
DispatchQueue.main.async {
success(responseString as AnyObject!)
}
})
task.resume()
}
func MultipartFormDataForSingleMediaRequset(showLoader: Bool, url:String, mediaData:Data?, mediaKey:String?, parameter:[String : AnyObject]?, success:#escaping (AnyObject!) -> Void, failed:#escaping (AnyObject!) -> Void) {
let startBoundry:String = "AaB03x"
let url = URL(string: url)!
var request:URLRequest = URLRequest(url: url as URL, cachePolicy: URLRequest.CachePolicy.reloadIgnoringLocalCacheData, timeoutInterval: 10)
request.allHTTPHeaderFields = getHeaderData(url: url.absoluteString)
let boundary:String = "--\(startBoundry)"
let endMPboundary:String = "\(boundary)--"
let imageData:Data = mediaData!
var body:String = String()
if parameter != nil {
for (key, value) in parameter! {
body = body + "\(boundary)\r\n"
body = body + "Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n"
body = body + "\(value)\r\n"
}
}
body = body + "\(boundary)\r\n"
body = body + "Content-Disposition: form-data; name=\"\(mediaKey!)\"; filename=\"\("attachment.png")\"\r\n"
body = body + "Content-Type: image/png\r\n\r\n"
let end:String = "\r\n\(endMPboundary)"
var myRequestData:Data = Data();
myRequestData.append(body.data(using: String.Encoding(rawValue: String.Encoding.utf8.rawValue))!)
myRequestData.append(imageData as Data)
myRequestData.append(end.data(using: String.Encoding.utf8)!)
let content:String = "multipart/form-data; boundary=\(startBoundry)"
request.setValue(content, forHTTPHeaderField: "Content-Type")
request.setValue("\(myRequestData.count)", forHTTPHeaderField: "Content-Length")
request.httpBody = myRequestData as Data
request.httpMethod = "POST"
let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: {
data, response, error in
guard let data = data, error == nil else {
print("O/P error=\(error.debugDescription)")
failed(error.debugDescription as AnyObject!)
self.stopProgressLoading()
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
print("O/P statusCode should be 200, but is \(httpStatus.statusCode)")
print("O/P response = \(String(describing: response))")
self.stopProgressLoading()
failed(response as AnyObject!)
}
let responseString = String(data: data, encoding: .utf8)
print("O/P responseString = \(String(describing: responseString))")
self.stopProgressLoading()
DispatchQueue.main.async {
success(responseString as AnyObject!)
}
})
task.resume()
}
private func startProgressLoading(isStart: Bool) {
DispatchQueue.main.async {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
}
private func stopProgressLoading() {
DispatchQueue.main.async {
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
}
}
func getProductDetail(productID:String, success: #escaping (ProductDetailDataModel?) -> Void, failed: #escaping (AnyObject!) -> Void) {
if isConnectedToInternet() {
theController.showLoader()
let addressURL = productDetailURL
let theParamDict = [WSKeys.product_id : productID] as [String: AnyObject]
NetworkManager.shared.POSTRequset(showLoader: true, url: addressURL, parameter: theParamDict , success: { (responseObject) in
self.theController.hideLoader()
guard let data = responseObject.object(forKey: "data") as? NSDictionary else {
success(nil)
return
}
guard let storeInfo = data.object(forKey: "productDetailsInfo") as? [String: AnyObject] else {
success(nil)
return
}
let dataArray = self.setStoreDetail(dictData: storeInfo)
success(dataArray)
}, failed: { (error) in
self.theController.hideLoader()
print("error is \(error)")
failed(error)
})
} else {
failed("No Internet Connection" as AnyObject)
}
}
struct ProductDetailDataModel {
var strStoreID: String? = nil
var strPrice:NSNumber? = nil
var strType:NSNumber? = nil
var strSellerID:String? = nil
var dicSeller:[String:AnyObject] = [:]
var arrStoreMedia: [[String: AnyObject]]?
mutating func setTheProperties(theDict: [String: AnyObject]) {
strStoreID = "\(String(describing: theDict["product_id"]!))"
strPrice = theDict["price"] as? NSNumber
dicSeller = theDict["seller"] as! [String:AnyObject]
arrStoreMedia = theDict["products_medias"] as? [[String: AnyObject]]
for product in arrStoreMedia!
{
if let photo_original = product["photo_original"] as? String, photo_original != ""
{
strPhotoOrignal = photo_original
break;
}
}
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tblHome.dequeueReusableCell(withIdentifier: "CellHeadetTC") as! CellHeadetTC
cell.advertisements = homeDetail.arrAdvertisement
return cell
}
else if indexPath.row == 1 {
let cell = tblHome.dequeueReusableCell(withIdentifier: "CellHomeTableView") as! CellHomeTableView
cell.selectionStyle = .none
cell.nav = self.navigationController
cell.arrCat = homeDetail.arrCategory
cell.collectionViewCategory.reloadData()
return cell
}
else {
let cell = tblHome.dequeueReusableCell(withIdentifier: "CellServiceTableView") as! CellServiceTableView
cell.selectionStyle = .none
if indexPath.row == 2 {
cell.lblheader.text = "Pending Service".localized()
cell.arrService = homeDetail.arrRecentService
cell.btnSeeAll.addTarget(self, action: #selector(HomeViewControlller.btnRecentSeeAllClicked(_:)), for: .touchUpInside)
}
else{
cell.lblheader.text = "Upcoming Services".localized()
cell.arrService = homeDetail.arrUpcommingService
cell.btnSeeAll.addTarget(self, action : #selector(HomeViewControlller.btnUpcomingSeeAllClicked(_:)), for: .touchUpInside)
}
return cell
}
}
var arrCategory = [Categorys]()
let temp = responseDict["data"]!.dictionaryValue
let arrCategory = temp["categories"]!.arrayValue
let homeClass = HomeClass()
for i in 0..<arrCategory.count {
let dict = arrCategory[i].dictionaryValue
let categoryData = Categorys()
categoryData.strId = dict["id"]?.stringValue
homeClass.arrCategory.append(categoryData)
}
I am learning swift and I send a request to the server with the code below. It works for simple request and I get response from the server. My problem is I can not send a file to server.
code :
let parameters = parameter
let request = NSMutableURLRequest(URL: NSURL(string: requestUrl)!)
let boundaryConstant = "-----Boundary+\(arc4random())\(arc4random())"
let contentType = "multipart/form-data; boundary=" + boundaryConstant
let boundaryStart = "--\(boundaryConstant)\r\n"
let boundaryEnd = "--\(boundaryConstant)--\r\n"
let body:NSMutableString = NSMutableString();
for (key, value) in parameters {
body.appendFormat(boundaryStart)
body.appendFormat("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.appendFormat("\(value)\r\n")
}
body.appendFormat(boundaryEnd)
request.HTTPMethod = "POST"
request.setValue(contentType, forHTTPHeaderField: "Content-Type")
request.HTTPBody = body.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
guard error == nil && data != nil else {
// check for fundamental networking error
print("error=\(error)")
return
}
if let httpStatus = response as? NSHTTPURLResponse where httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
}
self.responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)!
print("MMMMMMMM \(self.responseString)")
self.result = self.responseString.dataUsingEncoding(NSUTF8StringEncoding)! as NSData
callback(self.responseString)
}
print("code start")
task.resume()
result :
i can post file to server by this code:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let request = createRequest()
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
if error != nil {
// handle error here
print(error)
return
}
do {
if let responseDictionary = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? NSDictionary {
print("success == \(responseDictionary)")
}
} catch {
print(error)
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString)")
}
}
task.resume()
}
func createRequest () -> NSURLRequest {
let param = []
let boundary = generateBoundaryString()
let url = NSURL(string: "URl")!
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.setValue("userValue", forHTTPHeaderField: "X-Client-user")
request.setValue("passValue", forHTTPHeaderField: "X-Access-pass")
//let path1 = NSBundle.mainBundle().pathForResource("voice", ofType: "png") as String!
request.HTTPBody = createBodyWithParameters(param, filePathKey: "voice", paths: ["pathURl"], boundary: boundary)
return request
}
func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, paths: [String]?, boundary: String) -> NSData {
let body = NSMutableData()
if parameters != nil {
for (key, value) in parameters! {
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.appendString("\(value)\r\n")
}
}
if paths != nil {
for path in paths! {
let url = NSURL(fileURLWithPath: path)
let filename = url.lastPathComponent
let data = NSData(contentsOfURL: url)!
let mimetype = mimeTypeForPath(path)
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(data)
body.appendString("\r\n")
}
}
body.appendString("--\(boundary)--\r\n")
return body
}
func generateBoundaryString() -> String {
return "Boundary-\(NSUUID().UUIDString)"
}
func mimeTypeForPath(path: String) -> String {
let url = NSURL(fileURLWithPath: path)
let pathExtension = url.pathExtension
if let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension! as NSString, nil)?.takeRetainedValue() {
if let mimetype = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() {
return mimetype as String
}
}
return "application/octet-stream";
}
As you read here, you should use NSURLSession for HTTP work, it far more flexible and powerful; and I think is destined to replace NSURLconnection...
https://www.objc.io/issues/5-ios7/from-nsurlconnection-to-nsurlsession/
Here is a example for you...
func getMetaData(lePath:String, completion: (string: String?, error: ErrorType?) -> Void) {
// **** get_metadata ****
let request = NSMutableURLRequest(URL: NSURL(string: "https://api.dropboxapi.com/2/files/get_metadata")!)
let session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
request.addValue("Bearer ab-blah-blah", forHTTPHeaderField: "Authorization")
request.addValue("application/json",forHTTPHeaderField: "Content-Type")
request.addValue("path", forHTTPHeaderField: lePath)
let cursor:NSDictionary? = ["path":lePath]
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(cursor!, options: [])
request.HTTPBody = jsonData
print("json ",jsonData)
} catch {
print("snafoo alert")
}
let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
if let error = error {
completion(string: nil, error: error)
return
}
let strData = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Body: \(strData)\n\n")
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers);
self.jsonParser(jsonResult,field2file: "ignore")
for (key, value) in self.parsedJson {
print("key2 \(key) value2 \(value)")
}
completion(string: "", error: nil)
} catch {
completion(string: nil, error: error)
}
})
task.resume()
}
Great answer above.. Here it's updated for Swift3:
func getMetaData(lePath:String, completion: (string: String?, error: ErrorType?) -> Void) {
// **** get_metadata ****
let request = NSMutableURLRequest(URL: NSURL(string: "https://api.dropboxapi.com/2/files/get_metadata")!)
let session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
request.addValue("Bearer ab-blah-blah", forHTTPHeaderField: "Authorization")
request.addValue("application/json",forHTTPHeaderField: "Content-Type")
request.addValue("path", forHTTPHeaderField: lePath)
let cursor:NSDictionary? = ["path":lePath]
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(cursor!, options: [])
request.HTTPBody = jsonData
print("json ",jsonData)
} catch {
print("snafoo alert")
}
let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
if let error = error {
completion(string: nil, error: error)
return
}
let strData = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Body: \(strData)\n\n")
do {
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers);
self.jsonParser(jsonResult,field2file: "ignore")
for (key, value) in self.parsedJson {
print("key2 \(key) value2 \(value)")
}
completion(string: "", error: nil)
} catch {
completion(string: nil, error: error)
}
})
task.resume()
}
I'm trying o work out the correct (or at least a good) way to handle data request using Swift 2.
What i want to achieve is to:
Check if a data connection is available, if no then alert the user
If connection is available make a request
Check request response, if invalid then alert the user
if valid, check the response code and display one of 2 messages
what i have so far
let requestURL: String = **********************
let url = NSURL(string: requestURL)!
let request = NSMutableURLRequest(URL: url)
let session = NSURLSession.sharedSession()
let postParams: NSDictionary = ["id":newId!]
request.HTTPMethod = "POST"
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(postParams, options: [])
let jsonString = NSString(data: jsonData, encoding: NSUTF8StringEncoding)! as String
let utf8str = jsonString.dataUsingEncoding(NSUTF8StringEncoding)
let base64Encoded = utf8str?.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
let bodyData = "data="+base64Encoded!
request.HTTPBody = bodyData.dataUsingEncoding(NSUTF8StringEncoding)
} catch {
print("Error serialising JSON")
}
session.dataTaskWithRequest(request) { data, response, error in
// Make sure response is OK
guard let realResponse = response as? NSHTTPURLResponse where realResponse.statusCode == 200 else
{
// Show success message
print("Invalid Response from server")
}
// Read JSON Data
if let postString = NSString(data:data!, encoding: NSUTF8StringEncoding) as? String {
if let responseData = postString.dataUsingEncoding(NSUTF8StringEncoding) {
let json = JSON(data: responseData)
let responseMessage:String = json["response"]["data"].stringValue
if(responseMessage == "success")
{
print("successful post")
}else{
print("error saving post")
}
}
}
}
Currently if i was to run this in airplane mode then nothing happens, but i would like to catch this and tell these they need a data connection
Try sth like this:
func connectedToNetwork() -> Bool {
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)
let defaultRouteReachability = withUnsafePointer(&zeroAddress) {
SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
}
var flags = SCNetworkReachabilityFlags()
if !SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) {
return false
}
let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
return (isReachable && !needsConnection)
}
if(connectedToNetwork() == true){
//call your function to make the request
} else {
//show alert that they need an internet connection
}