Reputation: 49
The context is as follows: I wrote an app which can choose an image from your library and then it converts the image into base64 string as follows:
let imageData:NSData = UIImageJPEGRepresentation(self.myImageView.image!, 0.1)! as NSData
let strBase64 = imageData.base64EncodedString(options: .lineLength64Characters)
Here myImageView is where the image is stored when one chooses an image. Then I uploaded this into my local mysql database, where I have column of type MEDIUMTEXT. Then I wrote an app that could get this string from the database, but when I wanted to decode it and make it a UIimage again, my program failed. This is what I tried:
let dataDecoded:NSData = NSData(base64Encoded: tempString64, options: NSData.Base64DecodingOptions(rawValue: 0))!
let decodedimage:UIImage = UIImage(data: dataDecoded as Data)!
Here tempString64 is the string that I got from the database (I also checked that it is not empty). If I run the app I get an error that dataDecoded was nil while trying to unwrap it. I really don't understand why it is nil, while my tempString is really there.
Thanks.
UPDATE: I tried many things, but it is not working! Here is the relevant part of the code that I use now inside URLSession:
if data != nil {
do {
let imagesJSON = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSDictionary
let images : NSArray = imagesJSON["images"] as! NSArray
let temp : NSArray = images[0] as! NSArray
var tempString64 : String = temp[0] as! String
// I found a question on this site that said that the string should be of length multiple of 4, the following does that.
let remainder = tempString64.count % 4
if remainder > 0 {
tempString64 = tempString64.padding(toLength: tempString64.count + 4 - remainder,
withPad: "=",
startingAt: 0)
}
//check if string is not nil
print(tempString64)
let dataDecoded = Data(base64Encoded: tempString64)
let decodedimage = UIImage(data: dataDecoded!)
DispatchQueue.main.async {
self.myImageView.image = decodedimage
}
} catch {
print(error)
}
}
Tail of tempString64
wBr9KavclvUrxPlNp6ircQ5qNLTDfe/Sr8Vvj L9KqS0BbEM2AKz2rXmt8j736VRNr/ALX6UJEmcv3qnPSpRZ/N979Kn y8fe/SqKiZhNJV1rP/AGv0pPsf 1 lEkJlFhkYpAoQe9aH2Pj736VE1n/t/pTV7DRXjPzVpL0qGCy5yX/StEW2B979KLFrYzpadafxfhU8ltn L9Kktrbbu b07Uraktn/2Q==
Length of tempString64 is 13752
Upvotes: 1
Views: 5464
Reputation: 285072
The issue is caused by the lineLength64Characters
option. If this option is specified you have to decode the data with option ignoreUnknownCharacters
let dataDecoded = Data(base64Encoded: tempString64, options: .ignoreUnknownCharacters)!
But it's much easier to omit all options. The database doesn't care about nice formatting anyway.
let strBase64 = imageData.base64EncodedString()
...
let dataDecoded = Data(base64Encoded: tempString64)!
UPDATE:
Remove the padding code and get the encoded string safely. The API handles the padding for you.
Don't use NSArray
and NSDictionary
in Swift, use native type safe types. And never ever use .mutableContainers
particularly you assign the value to an immutable constant. The option is pointless in Swift.
if let data = data {
do {
if let imagesJSON = try JSONSerialization.jsonObject(with: data) as? [String:Any],
let images = imagesJSON["images"] as? [Any],
let temp = images.first as? [String],
let tempString64 = temp.first {
print(tempString64)
let dataDecoded = Data(base64Encoded: tempString64)
let decodedimage = UIImage(data: dataDecoded!)
DispatchQueue.main.async {
self.myImageView.image = decodedimage
}
}
} catch {
print(error)
}
}
Upvotes: 5