When I get my JSON back from my API this is how it looks
{
data:[
100,
80,
105,
99,
etc
]
}
How do I take this array and turn it back into a base64 string, then NSData and finally UIImage.
Here is what I have thus far.
let byteArray = todo["image"]["data"].arrayObject
var data = NSData(bytes: byteArray!, length: byteArray!.count)
var image = UIImage(data: data)
When printing the data it prints fine but returns nil for image.
Have you tried iterating throug the array and building a string from its elements, the use base64 encoding/decoding api to get back from string to NSData? Something like that(I'm writing from iPad so I can't check).
var encodedString=""
for smallString in byteArray {
encodedString += String(smallString)
}
let data = NSData(base64EncodedString: base64Encoded, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)
var image = UIImage(data: data)
let byteArray = todo["image"]["data"].arrayObject
let string = String(bytes: byteArray, encoding: .utf8)
let encodedImageData = string
let imageData = NSData(base64Encoded: encodedImageData!)
let image = UIImage(data: imageData! as Data)
Related
I am very confused on this one. I had been thinking it was something wrong with my server, but after testing it seems as though using Data(base64encoded: data) is producing nil even though the data is there and is in fact base64encoded.
I have tried everything I can think of and nothing is working. Here is the code I am using and the output...
do {
print("DATA as a string: ", String(data: data!, encoding: .utf8) ?? "NONE AVAILABLE")
let decodedData = Data(base64encoded: data!, options: .ignoreUnknownCharacters)
print("DECODED DATA: ")
print(decodedData as Any)
let apiResponse = try JSONDecoder().decode(ApiConnectionResponse.self, from: decodedData!)
completion(.success(apiResponse))
} catch {
completion(.failure(error))
}
The output from that is...
Data as string:
eyJzdWNjZXNzIjoiZmFsc2UiLCJlcnJvciI6Im1vYmlsZV9waW5fY29ubmVjdDogaW52YWxpZCBvciBleHBpcmVkIn0.
DECODED DATA: nil
So the String is a legit base64encoded string, it decodes to
{"success":"false","error":"mobile_pin_connect: invalid or expired"}
However the decoded data is nil. I don't understand, how can it be nil when the string is a base64encoded string and is not nil.
I have even tried forcing the string in there like so...
let decodedData = Data(base64encoded: String(data: data!, encoding: .utf8))
Still no luck. It is throwing a fatal error, and I can see in the section at the bottom of Xcode that the data is in fact "(Data?) 92 bytes" What I can't figure out is why it is nil after running through Data()...
Any help would be greatly appreciated, I am really lost and can't figure out why I can make the string, but not the data.
The end result of this is, I need to get JSONDecoder().decode to work with the reply from the server, I think I can get that part done, if I can figure out why it is nil after the data call. Thank you.
You need to check your data length, divide by 3 and in case the result is not zero add one or two bytes (65) = equal sign for padding your data. Try like this:
let decodedData = Data(base64Encoded: data + .init(repeating: 65, count: data.count % 3))
extension Data {
var base64encodedDataPadded: Data {
let data = last == 46 ? dropLast() : self
return data + .init(repeating: 65, count: data.count % 3)
}
}
Playground testing:
let data = Data("eyJzdWNjZXNzIjoiZmFsc2UiLCJlcnJvciI6Im1vYmlsZV9waW5fY29ubmVjdDogaW52YWxpZCBvciBleHBpcmVkIn0.".utf8)
let decodedData = Data(base64Encoded: data.base64encodedDataPadded)!
print(String(data: decodedData, encoding: .utf8)!) // "{"success":"false","error":"mobile_pin_connect: invalid or expired"}"
I guess the encoded data is wrong.
let originalString = """
{"success":"false","error":"mobile_pin_connect: invalid or expired"}
"""
let base64string = originalString.data(using: .utf8)?.base64EncodedString()
print(base64string)
let base64EncodedData = originalString.data(using: .utf8)?.base64EncodedData()
let base64EncodedString = String(data: base64EncodedData!, encoding: .utf8)
print(base64EncodedString)
let decodedData = Data(base64Encoded: base64EncodedData!)
let decodedString = String(data: decodedData!, encoding: .utf8)
print(decodedString)
The log is as below:
Optional("eyJzdWNjZXNzIjoiZmFsc2UiLCJlcnJvciI6Im1vYmlsZV9waW5fY29ubmVjdDogaW52YWxpZCBvciBleHBpcmVkIn0=")
Optional("eyJzdWNjZXNzIjoiZmFsc2UiLCJlcnJvciI6Im1vYmlsZV9waW5fY29ubmVjdDogaW52YWxpZCBvciBleHBpcmVkIn0=")
Optional("{\"success\":\"false\",\"error\":\"mobile_pin_connect: invalid or expired\"}")
According to the base64 specification, . is not a valid character. = is the appropriate character for padding.
https://en.wikipedia.org/wiki/Base64
You show your base64 string as having a period and a newline at the end. That doesn't look correct. An online base64 decoder decodes it with or without that final period and newline, but Swift probably chokes with it in place.
i am new in IOS and i am making a project in which i receive Base64 data from web service. how to convert Base64 data into string and how to open a pdf view in swift and also check that is there any pdf owner application install or not in iPhone .and i want to know that how to convert NSDATA in string swift.Help me
example like this is Base64 data
JVBERi0xLjQKJcfsj6IKNSAwIG9iago8PC9MZW5ndGggNiAwIFIvRmlsdGVyIC9GbGF0ZURlY29kZT4+CnN0cmVhbQp4nLVcza8ct5GH1rK9ejIU24lkO5GtJ8vWm5E87eY3uXtbYLHAYi8JdItySrABAjhA8v8fUuwmu35kF2fmxbsWDMxjk8VisapYX+TfbudJ6ds5/6s//vj
Like this is nsdata
<25504446 2d312e34 0a25c7ec 8fa20a35 2030206f 626a0a3c 3c2f4c65 6e677468 20362030 20522f46 696c7465 72202f46 6c617465 4465636f 64653e3e 0a737472 65616d0a 789cb55c cdaf1cb7 9187d6b2 bd7a3214 db89643b 91ad27cb d69b913c
There are two parts to this question. First, converting the base 64 string into a Data/NSData. But you've done that already, so you don't need help there.
Second, converting that Data/NSData into a string. But, if you look at that file carefully, you'll see that data is a PDF file, not a text string. For example, if I save that as a file and look at it in a hex editor, I can clearly see it's a PDF:
You can't just convert that PDF binary data to a string. (In fact, that's why it was base64-encoded in the first place, because it was complex binary data.)
But you can, for example, use UIDocumentInteractionController to preview the PDF file that you saved to a file.
For example:
// convert base 64 string to data
let base64 = "JVBERi0xLjQKJcfsj6IKNSAwIG9iago8PC9MZW5ndGggNiAwIFIvRmlsdGVyIC9GbGF0ZURlY29kZT4+CnN0cmVhbQp4nLVcza8ct5GH1rK9ejIU24lkO5GtJ8vWm5E87eY3uXtbYLHAYi8JdItySrABAjhA8v8fUuwmu35kF2fmxbsWDMxjk8VisapYX+TfbudJ6ds5/6s/"
guard let data = Data(base64Encoded: base64) else {
print("unable to convert base 64 string to data")
return
}
// given the data was PDF, let's save it as such
let fileURL = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
.appendingPathComponent("test.pdf")
try! data.write(to: fileURL)
// if it was a string, you could convert the data to string, but this will fail
// because the data is a PDF, not a text string
//
// guard let string = String(data: data, encoding: .utf8) else {
// print("Unable to convert data into string")
// return
// }
// print(string)
// So, instead, let's use `UIDocumentInteractionController` to preview the PDF:
let controller = UIDocumentInteractionController(url: fileURL)
controller.delegate = self
controller.presentPreview(animated: true)
Where, the view controller conforms to UIDocumentInteractionControllerDelegate:
extension ViewController: UIDocumentInteractionControllerDelegate {
func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
return self
// or, if this view controller is already in navigation controller, don't
// return `self`, like above, but instead return the navigation controller itself
//
// return navigationController!
}
}
From Base64 to Data to String.
let base64String = "dGhpcyBpcyBmb3IgdGVzdGluZw=="
if let data = Data(base64Encoded: base64String) {
if let string = String(data: data, encoding: .utf8) {
print(string)
}
}
From Base64 to NSData to String.
let data = NSData(base64Encoded: base64String, options: .ignoreUnknownCharacters)
var string = String(data: data, encoding: .utf8)
}
Swift 3.0
A handy extension of string. Hope will help you.
extension String {
func fromBase64() -> String? {
guard let data = Data(base64Encoded: self) else {
return nil
}
return String(data: data, encoding: .utf8)
}
func toBase64() -> String {
return Data(self.utf8).base64EncodedString()
}
}
I'm trying to send image to server via JSON string. Problem is the server didn't see my image in PNG or JPG format. Here is code how i do it:
enter image description here
That how i convert parameters to JSON string
enter image description here
What i want - it's encode UIImage to base64 string and send to server.
Thank You!
try using the below code and check if any error occurs or image value is nil
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
if let imageData = UIImageJPEGRepresentation(image, 0.5) {
let base64String = imageData.base64EncodedString(options: Data.Base64EncodingOptions.init(rawValue: 0))
let dict: [String: Any] = ["data": base64String]
do {
let data = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
if let string = String(data: data, encoding: .utf8) {
socket.write(string)
}
} catch {
print(error.localizedDescription)
}
}
}
This is how I create Data from UIImage:
let data = UIImagePNGRepresentation(image)
And then I need to convert it to String;
if let data = data {
let stringFromData = String(data: data, encoding: .utf8)
}
but stringFromData is nil. Why?
You can get it using the Data method base64EncodedString()
if let data = data {
let stringFromData = data.base64EncodedString()
// to decode base 64 string you can use Data base64Encoded String initializer
if let dataFromBase64 = Data(base64Encoded: stringFromData) {
print(data)
}
}
Convert Your image data in Base64 string
For Encode
let stringFromData : Data = Data(base64Encoded: strBase64, options: .ignoreUnknownCharacters)!
And decode
let strBase64 = imageData.base64EncodedStringWithOptions(.allZeros)
I'm kinda new to swift and i need some help with encoding some image, putting it in a JSON and after retrieving it, decoding it back to NSData and recreating the image in an UIImage view controller.
I've found this post Convert Image to Base64 string in iOS + Swift but i get stuck with this part:
let decodedData = NSData(base64EncodedString: base64String, options: NSDataBase64DecodingOptions.fromRaw(0)!)
because the fromRaw method is not available anymore.
Thanks in advance
Later edit:
I'm using swiftyJson to parse the array and i'm getting the image data like this:
var base64String = arrayJson[0]["photo"].stringValue
var imageString = base64String as NSString
and after that i'm trying to decode it like this:
let decodedData = NSData(base64EncodedString: imageString, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)
I've also tried with the rawValue instead of IgnoreUnknownCharacters. Both return nil. Also tried with the base64String instead of imageString. Same thing.
You can do the following instead to make a base64 encoded string to an UIImage:
//base64 string to NSData
let decodedData = NSData(base64EncodedString: base64String, options: NSDataBase64DecodingOptions(rawValue: 0))
//NSData to UIImage
var decodedIamge = UIImage(data: decodedData!)
NSDataBase64EncodingOptions.fromRaw(0)! now is changed to NSDataBase64DecodingOptions(rawValue: 0)
For more encode/decode details, you can visit this post: Convert between UIImage and Base64 string
To encode an image:
let image = UIImage(...)
let quality = 1.0
let data: NSData = UIImageJPEGRepresentation(image, quality)!
To decode an image:
let decodedImage = UIImage(data: data)
The reason why these methods return nil for you could be that your base64string is an URL and Filename safe variant, meaning character 62 (0x3E) is replaced with a "-" (minus sign) and character 63 (0x3F) is replaced with a "_" (underscore) as noted here base64 alphabet
Try replacing character _ with / and character - with + in your string.
You could use the following code:
base64string = base64string.stringByReplacingOccurrencesOfString("-", withString: "+", options: NSStringCompareOptions.LiteralSearch, range: nil)
base64string = base64string.stringByReplacingOccurrencesOfString( "_" , withString: "/", options: NSStringCompareOptions.LiteralSearch, range: nil)
Also be aware of the correct length of the string. it has to be a multiple of 4
- take a look at this answer padded string.
NSData Class Reference : https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/index.html#//apple_ref/c/tdef/NSDataBase64DecodingOptions
NSDataBase64DecodingOptions :
struct NSDataBase64DecodingOptions : RawOptionSetType {
init(_ rawValue: UInt)
init(rawValue rawValue: UInt)
static var IgnoreUnknownCharacters: NSDataBase64DecodingOptions { get }
}
Have you tried one of the followings :
let decodedData = NSData(base64EncodedString: base64String, options: NSDataBase64DecodingOptions(rawValue: 0)!)
let decodedData = NSData(base64EncodedString: base64String, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)