Only one emoji image display in my app - ios

I am building chat app and need to send and receive emoji images. I use following code to post data :
let myUrl = NSURL(string: "http://test.php")
let request = NSMutableURLRequest(URL:myUrl!)
request.HTTPMethod = "POST"
let postString = " shareImageMessage=\(message)"
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
I can see my message with emojies in debug area as follows :
But only following image display in mysql database :
And following code from php script :
$shareImageMessage = $_POST["shareImageMessage"];
I couldn't understand why only one kind of image transferring.

To send more than one emoticon in the same url simply convert the string you are sending to the server to a base64 and then decode it on the other end of the database. To Encode and Decode strings to base64 you can check this Convert between UIImage and Base64 string. :)

SWIFT: encode the message with base64 like so:
func base64encode(message: NSString)->String{
let plainData = message.dataUsingEncoding(NSUTF8StringEncoding)
return plainData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.fromRaw(0))!
}
usage : let msgToPost = base64encode("born to be encoded 👻")
then in PHP just use the famous $decodedmsg = base64_decode($str);
this code worked perfectly for me
one more thing..
make sure that your database column supports emoji, you can refer to the question for more detail about fixing the database emoji thing
How to insert utf-8 mb4 character(emoji in ios5) in mysql?

Related

Swift URL.path changes encoding of utf-8 characters

Why does converting a String to an URL in Swift 4.2 and then converting the URL back to a String using url.path change the encoding of special characters like german umlauts (ä, ö, ü), even if I use a utf-8 encoding?
I wrote some sample code to show my problem. I encoded the strings to base64 in order to show that there is a difference.
I also have a similar unsolved problem with special characters and swift here.
Sample Code
let string = "/path/to/file"
let stringUmlauts = "/path/to/file/with/umlauts/testäöü"
let base64 = Data(string.utf8).base64EncodedString()
let base64Umlauts = Data(stringUmlauts.utf8).base64EncodedString()
print(base64, base64Umlauts)
let url = URL(fileURLWithPath: string)
let urlUmlauts = URL(fileURLWithPath: stringUmlauts)
let base64Url = Data(url.path.utf8).base64EncodedString()
let base64UrlUmlauts = Data(urlUmlauts.path.utf8).base64EncodedString()
print(base64Url, base64UrlUmlauts)
Output
The base64 and base64Url string stay the same but the base64Umlauts and the base64UrlUmlauts are different.
"L3BhdGgvdG8vZmlsZQ==" for base64
"L3BhdGgvdG8vZmlsZQ==" for base64Url
"L3BhdGgvdG8vZmlsZS93aXRoL3VtbGF1dHMvdGVzdMOkw7bDvA==" for base64Umlauts
"L3BhdGgvdG8vZmlsZS93aXRoL3VtbGF1dHMvdGVzdGHMiG/MiHXMiA==" for base64UrlUmlauts
When I put the base64Umlauts and base64UrlUmlauts strings into an online Base64 decoder, they both show /path/to/file/with/umlauts/testäöü, but the ä, ö, ü are different (not visually).
stringUmlauts.utf8 uses the Unicode characters äöü.
But urlUmlauts.path.utf8 uses the Unicode characters aou each followed by the combining ¨.
This is why you get different base64 encoding - the characters look the same but are actually encoded differently.
What's really interesting is that Array(stringUmlauts) and Array(urlUmlauts.path) are the same. The difference doesn't appear until you perform the UTF-8 encoding of the otherwise exact same String values.
Since the base64 encoding is irrelevant, here's a more concise test:
let stringUmlauts = "/path/to/file/with/umlauts/testäöü"
let urlUmlauts = URL(fileURLWithPath: stringUmlauts)
print(stringUmlauts, urlUmlauts.path) // Show the same
let rawStr = stringUmlauts
let urlStr = urlUmlauts.path
print(rawStr == urlStr) // true
print(Array(rawStr) == Array(urlStr)) // true
print(Array(rawStr.utf8) == Array(urlStr.utf8)) // false!!!
So how is the UTF-8 encoding of two equal strings different?
One solution to this is to use precomposedStringWithCanonicalMapping on the result of path.
let urlStr = urlUmlauts.path.precomposedStringWithCanonicalMapping
Now you get true from:
print(Array(rawStr.utf8) == Array(urlStr.utf8)) // now true

Emojis showing up as question marks in app made using swift(iOS), java(android), ruby(server), mongodb(database)

I've been working on this chatting application in which users can send emojis. Now I'm taking the string from whatever user enters in the UITextField and put it in NSDictionary and sending it to the server as json. And that json is sent to the server where the message is read as string in ruby and then stored in mongodb. Now when the other client make the get messages api call, the emojis are showing up as a box or a '?'.
P.S : only emojis with 5 character code shows up like that for eg: \u1F602
but the emojis with 4 character code shows up fine for eg: \u2764
Now I don't know if the problem is client or server or the database so I don't know which code to add here. Please add in comments the code you need I'll post it here.
It feels like the problem is server, cause the problem is caused in both android and iOS devices.
Have been banging my head on this for more than a month now. Would love if someone can help.
Thanks
----EDIT----
I understand that in ruby \u{1F602} works but I don't know how to make the clients send it in that format. I'm just taking whatever user types in the UITextField(for iOS) and EditText(for Android) and sending them as it is.
Is there a way I can make that change in client or fix it on server somehow?
In iOS,
For encode emojis to unicode use below code:
let msg:String = "😂😂"
extension String {
var encodeEmoji: String{
if let encodeStr = NSString(cString: self.cString(using: .nonLossyASCII)!, encoding: String.Encoding.utf8.rawValue){
return encodeStr as String
}
return self
}
}
let msgdata:String = msg.encodeEmoji
send encoded string to server..
For decode unicode to emojis use below code:
While getting your responce from the server which is unicode.
decode that unicode to Emoji with below code
extension String {
var decodeEmoji: String{
let data = self.data(using: String.Encoding.utf8);
let decodedStr = NSString(data: data!, encoding: String.Encoding.nonLossyASCII.rawValue)
if let str = decodedStr{
return str as String
}
return self
}
}
let decodedstring = "Your Unicode String".decodeEmoji
If anyone is looking for an answer. This is how I fixed it
For Android:
in your gradle file add the following dependency
compile 'org.apache.commons:commons-lang3:3.6'
and then while sending a message to server encode the text using this
String msg = "User message here with emoji";
msg = StringEscapeUtils.escapeJava(msg);
and to decode the message after receiving from the server, use the following command
String msg = "User message here with emoji";
msg = StringEscapeUtils.unescapeJava(text);
For iOS:
(Using #Ankit Chauhan's answer)
let msg:String = "😂😂"
extension String {
var encodeEmoji: String{
if let encodeStr = NSString(cString: self.cString(using: .nonLossyASCII)!, encoding: String.Encoding.utf8.rawValue){
return encodeStr as String
}
return self
}
}
let msgdata:String = msg.encodeEmoji
And to decode use this:
extension String {
var decodeEmoji: String{
let data = self.data(using: String.Encoding.utf8);
let decodedStr = NSString(data: data!, encoding: String.Encoding.nonLossyASCII.rawValue)
if let str = decodedStr{
return str as String
}
return self
}
}
let decodedstring = "Your Unicode String".decodeEmoji
The simplified notation without curly brackets assumes there are four digits following \u. For 3-bytes one should use the complete expression:
â–¶ "\u{1F602}"
#⇒ "😂"
For Android I had to do 2 things.
Use escapeJava when i send msg to server and unescapeJava when receive msg
'org.apache.commons:commons-lang3' //deprecated, dont use
org.apache.commons:commons-text:1.2'
StringEscapeUtils.escapeJava(message)
StringEscapeUtils.unescapeJava(message)
Use EmojiCompat library from google
https://developer.android.com/guide/topics/ui/look-and-feel/emoji-compat.html

NSUrl swift 2 with greek and other special characters

I'm trying to make a server request with
NSUrl(string: "http://example.com/α")
In which α is a greek character. So when i request this i get an error and my app crashes. So i tried to encode the url to this
let myUrl = NSURL(string: myLink.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)!
and now my link has become http://example.com/%CE%B1
where %CE%B1 is the α character. Although my server does not recognise it and it doesnt send me back the data.
I use node.js with io.socket connections. Is there any way with swift to send the correct url without the percent encoding?
For encode α in your url
let str = "α"
let url = str.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())
Now decode url string like this
let orgStr = url?.stringByRemovingPercentEncoding
print(orgStr)

How to POST integer request to server in swift ios?

let theRequest = NSMutableURLRequest(URL: url!)
theRequest.HTTPMethod = "POST"
let parameters = ["otp":firstDigit.text!,"otp":secondDigit.text!,"otp":thirdDigit.text!,"otp":fourthDigit.text!] as Dictionary<String,String>
How to add parameters to pass numbers in to the server side. There is only one field in the server side and I have to pass 4 integers using four different text fields. How can I pass it? Basically I am passing an OTP(One time password with four digits)
First make the OTP variable like this:-
var otpText:String= firstDigit.text + secondDigit.text +thirdDigit.text+fourthDigit.text
then form the parameter:-
let parameters : NSDictionary =["otp":otpText]
Have you checked out the property HTTPBody: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSMutableURLRequest_Class/#//apple_ref/occ/instp/NSMutableURLRequest/HTTPBody
Not compiled myself, but would be something like:
let otp = firstDigit.text + secondDigit.text+thirdDigit.text+fourthDigit.text
let json = [ "OTP" : otp ]
let jsonData = NSJSONSerialization.dataWithJSONObject(json, options: NSJSONWritingOptions.allZeros, error: nil)
theRequest.HTTPBody = jsonData
What this code does:
Concatenate your text values to make a string
Create a dictionary (JSON object) with the key your server expected
and the value of the concatenated string
Convert that dictionary to NSData as expected by the HTTPBody property
Set the HTTPBody property on your NSMutableURLRequest
Also checkout out https://github.com/AFNetworking/AFNetworking. It makes it super simple to handle HTTP requests using iOS.

uploading image in swift with multiple parameters

I am trying to upload an image to a backend client using swift. Trouble is I can't seem to get the formatting correct for the httpbody. I do not want to use a multipart form for uploading as I don't know how to handle that on the backend.
Here is the code I have.. it doesn't work when I view the image online it doesn't display and it is only like 70kb which I know is definitely not how big the image is.
var bodyString: String = "session_id=\(session_id)&location_id=\(location_id)"
bodyString = bodyString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
var body = NSMutableData.alloc()
body.appendData(bodyString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)
if image != nil{
var imageData = UIImageJPEGRepresentation(image,0.5)
body = NSMutableData.alloc()
//var imageDataString = imageData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
bodyString = "session_id=\(session_id)&location_id=\(location_id)&image_data="
bodyString = bodyString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
body.appendData(bodyString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)
var imageString = "&image_data=\(imageData)"
body.appendData(imageData)
}
req.HTTPBody = body
UPDATE:
so I decided to go the base64 route but it still doesn't seem to be working I think because I am encoding it as an ntf8string is this the correct way to be doing this?
var imageData = UIImageJPEGRepresentation(image,0.5)
var imageDataString = imageData.base64EncodedStringWithOptions(.allZeros)
body = NSMutableData.alloc()
bodyString = "session_id=\(session_id)&location_id=\(location_id)&tag_type=\(tag_type)&image_data=\(imageDataString)"
bodyString = bodyString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
body.appendData(bodyString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)
and on the backend I am decoding it like:
image_data_decoded = base64.b64decode(image_data)
You cannot post binary data in a application/x-www-form-urlencoded request like this. Actually, the code in your question looks like it will try to send a hexadecimal string representation of the binary data, which, probably is not what you intended and even if you did intend to do that, (a) you would have to decode it somehow on the server side; (b) note that this is very inefficient (more than doubles the size of the image payload): and (c) would need to be percent escaped in the request. But I don't think you intended that at all, anyway, so that is probably all moot.
One would generally either create multipart/form-data request as outlined here (in which the uploaded file comes in as a file, e.g. $_FILES in PHP), or one would convert this binary data to text (e.g. using base64) and the the server code has convert the base64 value for image_data key back to binary data.
By the way, I might suggest Alamofire or AFNetworking as alternatives to trying to create requests properly. It doesn't change the underlying issue (you have to pick between a base64 encoding or multipart requests), but it simplifies the Swift code.

Resources