I'm using the Vapor framework to download a PDF file :
let logpw = "myLogin:passWord"
let url = "https://someRESTsite/invoices/1.pdf"
let utf8str = logpw.data(using: String.Encoding.utf8)
let base64Encoded = utf8str?.base64EncodedString()
let response = try drop.client.get(url, headers:["Authorization":"Basic " + base64Encoded!])
this works fine. Note that I'm base64 encoding the login/pw for basic auth and this works for logging in and getting the file. Now I have to embed that PDF into an XML file in base64 using similar code:
if let bodyBytes = response.body.bytes {
let bodyByteString = try String(bytes: bodyBytes)
let utf8String = bodyByteString(using: String.Encoding.utf8)
let base64String = utf8String?.base64EncodedString()
}
the result is a string that actually really looks like a base64 string, but it's different than converting the same PDF using an online tool (I tried 2 which gave the same result).
Where is my mistake?
Related
I have a URL in the form of
foo://?data:application/x-foo;base64,OjAyMDAwMDA0MDAwMEZBDQo6MTAwMDA...
and now need to extract the base64 data into a Data object.
Unfortunately it seems the Data object does not support this yet as
let data = try Data(contentsOf: url)
returns NSURLConnection finished with error - code -1002 when trying.
While I could decode the URL manually I am wondering if I am missing a simple standard way of doing this. How would you do this?
Actually you can decode Base64 data from an URL (see for
example Base64 Decoding in iOS 7+ where this is demonstrated in Objective-C). The format is a bit different from what
you have:
let url = URL(string: "data:application/octet-stream;base64,SGVsbG8gd29ybGQh")!
let data = try! Data(contentsOf: url)
print(String(data: data, encoding: .utf8)!) // Hello world!
(Error checking omitted for brevity.)
You have to separate the base64 encoded part of the URL from the other parts, decode it, then join the original non-encoded part with the decoded part and get the data from there.
extension URL {
init?(partialBase64Url: String){
guard let base64part = base64Url.components(separatedBy: "base64,").last, let base64Data = Data(base64Encoded: base64part), let decodedString = String(data: base64Data, encoding: .utf8) else {
return nil
}
let decodedUrl = base64Url.components(separatedBy: "base64,").dropLast().joined() + decodedString
self.init(string: decodedUrl)
}
}
let decodedUrl = URL(partialBase64Url: "foo://?data:application/x-foo;base64,dGVzdFVybFN0cmluZw==")
Value of decodedUrl: "foo://?data:application/x-foo;testUrlString", as expected, since dGVzdFVybFN0cmluZw== is the base64 encoded value of testUrlString.
I have a .docx file in my temporary storage:
let location: NSURL = NSURL.fileURLWithPath(NSTemporaryDirectory())
let file_Name = location.URLByAppendingPathComponent("5 November 2016.docx")
What I now want to do is extract the text inside this document. But I cannot seem to find any converters or methods of doing this.
I have tried this:
let file_Content = try? NSString(contentsOfFile: String(file_Name), encoding: NSUTF8StringEncoding)
print(file_Content)
However it prints nil.
So how do I read the text in a docx file?
Swift 4, Xcode 9.1, OSX targets from 10.10 to 10.13
I have found that the following code extracts text handily from a Word .doc file, which then easily goes into a string. (The attributed string contains formatting information that might be parsed to good effect.) The main info that I wanted to convey was the bit about using .docFormat to specify the document type.
let openPanel = NSOpenPanel()
var fileString = String("")
var fileData = NSData()
let fileURL = openPanel.url
do {
fileData = try NSData(contentsOf: fileURL!)
if let tryForString = try? NSAttributedString(data: fileData as Data, options: [
.documentType: NSAttributedString.DocumentType.docFormat,
.characterEncoding: String.Encoding.utf8.rawValue
], documentAttributes: nil) {
fileString = tryForString.string
} else {
fileString = "Data conversion error."
}
fileString = fileString.trimmingCharacters(in: .whitespacesAndNewlines)
} catch {
print("Word Document File Not Found")
}
Your initial issue is with how you get the string from the URL. String(File_Name) is not the correct way to convert a file URL into a file path. The proper way is to use the path function.
let location = NSURL.fileURLWithPath(NSTemporaryDirectory())
let fileURL = location.URLByAppendingPathComponent("My File.docx")
let fileContent = try? NSString(contentsOfFile: fileURL.path, encoding: NSUTF8StringEncoding)
Note the many changes. Use proper naming conventions. Name variables more clearly.
Now here's the thing. This still won't work because a docx file is a zipped up collection of XML and other files. You can't load a docx file into an NSString. You would need to use NSData to load the zip contents. Then you would need to unzip it. Then you would need to go through all of the files and find the desired text. It's far from trivial and it is far beyond the scope of a single stack overflow post.
I am trying to import Json data from a user uploaded txt file into a standard object that I can use via SwiftyJson framework
Here is the contents of the text fie:
{
"String": "answer",
"String2": "answer2"
}
I have successfully read it and turned it into a String file using:
let openPanel = NSOpenPanel()
let arrayOfExtensions = ["txt"]
openPanel.allowedFileTypes = arrayOfExtensions
let result = openPanel.runModal()
if result == NSFileHandlingPanelCancelButton {
return
}
let fileUrl = openPanel.URL
do {
let stringResult = try String(contentsOfURL: fileUrl!, encoding: NSUTF8StringEncoding)
print (stringResult)
completionhandler(retrievedData: stringResult, error: nil)
I am trying to convert this into a JSON object using:
let jsonFile = JSON(contentsOfFile)
The problem is that the resulting JSON object created appears to be blank for all the fields except rawvalue.
Here is the screenshot from the debug console.
How to I sucessfully read in the string from the file and then make it populate via SwiftJson correctly?
The problem above was that I was using the wrong method to parse it into JSON.
SwiftyJSON seems to be badly documented hence others had a similar problem.
The correct way to do this is to use :
let jsonFile = JSON.parse(string:contentsOfFile)
I'm using zaph's example for encryption and decryption from this post
The encryption works well, and with my encryption key and iv, returns an NSData object, containing the following string: "bc6983a8 65d412df 2bafdc40 f569874e", which is my input text encrypted. The content of the returned NSData object:
encrypted text: <bc6983a8 65d412df 2bafdc40 f569874e>
This text is sent to a server (json), and the server returns a response, also encrypted with the same encryption key and iv.
My question is, how can I convert the string text that comes from the server's response(bc6983a8 65d412df 2bafdc40 f569874e, for example) into an NSData object so that i can decrypt it?
I tried the follwing:
let plainData = ("<bc6983a8 65d412df 2bafdc40 f569874e>" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!;
let plainData = ("<bc6983a8 65d412df 2bafdc40 f569874e>" as NSString).dataUsingEncoding(NSUTF8StringEncoding)!;
let base64String = plainData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0));
let dataDec = NSData(base64EncodedString: base64String, options: NSDataBase64DecodingOptions(rawValue: 0))
But when displaying the contents of the NSData object, the output is not the one expected:
data Optional("<3c626336 39383361 38203635 64343132 64662032 62616664 63343020 66353639 38373465 3e>")
Any help is appreciated.
You are converting your NSData to the string in a wrong way. Follow this code to convert NSData to string
//This is your encrypted data
var encryptedData = NSData()
let plainData = encryptedData(data: encryptedData, encoding: NSUTF8StringEncoding)
Hope this will work for you.
UPDATE:
This happens because you are not correctly fetching the string from your backend. Use proper method for decoding json data instead of just printing it. "<bc6983a8 65d412df 2bafdc40 f569874e>" is not the string you actually need. You need to decode your json data
See the sample code
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil
{
print("error=\(error)", terminator: "")
return
}
do{ if let newdata = try? (NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments) as! NSDictionary)
{
print(newdata)
}
Here 'newdata' may include the encrypted string you need. Parse it from that json, convert it to NSData and then decrypt.
UPDATE 2
Use this code to convert your data to string
let resstr = NSString(data: YourData, encoding: NSUTF8StringEncoding)
I'm trying to learn the new Swift programming language. It looks great, but I'm having a difficult time doing something as simple as reading the content of a local .txt file.
I have tried the few examples I could find through Google, but they give compile errors, like this answer here: Read and write data from text file
If I tweak the code a bit, it works, but can only read from a special location within the project.
Why isn't it just as simple to read a .txt file with Swift as it is with for instance Ruby? And how would I go about reading the content of a file located at ~/file.txt?
Thnx
If you have a tilde in your path you can try this:
let location = "~/file.txt".stringByExpandingTildeInPath
let fileContent = NSString(contentsOfFile: location, encoding: NSUTF8StringEncoding, error: nil)
otherwise just use this:
let location = "/Users/you/Desktop/test.txt"
let fileContent = NSString(contentsOfFile: location, encoding: NSUTF8StringEncoding, error: nil)
This gives you a string representation of the file, which I assumed is what you want.
You can use NSData(contentsOfFile: location) to get a binary representation, but you would normally do that for, say, music files and not a text file.
Update: With Xcode 7 and Swift 2 this doesn't work anymore. You can now use
let location = NSString(string:"~/file.txt").stringByExpandingTildeInPath
let fileContent = try? NSString(contentsOfFile: location, encoding: NSUTF8StringEncoding)
let file = "/Users/user/Documents/text.txt"
let path=URL(fileURLWithPath: file)
let text=try? String(contentsOf: path)
This would work:
let path = "~/file.txt"
let expandedPath = path.stringByExpandingTildeInPath
let data: NSData? = NSData(contentsOfFile: expandedPath)
if let fileData = data {
let content = NSString(data: fileData, encoding:NSUTF8StringEncoding) as String
}
Note that data may be nil, so you should check for that.
EDIT:
Don't forget conditional unwrapping - looks much nicer ;)
Relative path tip:
Instead of doing this:
NSString("~/file.txt").stringByExpandingTildeInPath
You can do this:
"\(NSHomeDirectory())/file.txt"
You may find this tool useful to not only read from file in Swift but also parse it simultaneously: https://github.com/shoumikhin/StreamScanner
Just specify the file path and data delimiters like this (see readme for more options):
import StreamScanner
if let input = NSFileHandle(forReadingAtPath: "/file/path")
{
let scanner = StreamScanner(source: input, delimiters: NSCharacterSet(charactersInString: ":\n")) //separate data by colons and newlines
while let field: String = scanner.read()
{
//use field
}
}
Hope, this helps.
Using the answer by Atomix, this will work in Swift 4:
let location = NSString(string: "~/test.txt").expandingTildeInPath
let fileContent = try? NSString(contentsOfFile: location, encoding: String.Encoding.utf8.rawValue)
This worked for me in Swift 2.1, XCode7 to get the location and print the contents of CSV. ( you can create a simple CSV in Text Wrangler)
override func viewDidLoad() {
super.viewDidLoad()
let location = NSString(string:"/Users/*Myusername*/Documents/myCSVfile.csv")
let fileContent = try? NSString(contentsOfFile: location as String, encoding: NSUTF8StringEncoding)
print(fileContent)
}
Swift 4:
let filePath = "/Users/UserName/Desktop/FolderName/FileName.txt"
let fullPath = NSString(string: filePath).expandingTildeInPath
do
{
let fileContent = try NSString(contentsOfFile: fullPath, encoding: String.Encoding.utf8.rawValue)
print(fileContent)
}
catch
{
print(error)
}
filename doesn't need to have scheme like file://, and can be relative like ../docs/test.txt.
Remember to catch any error thrown, or rethrow.
let url = URL(fileURLWithPath: filename)
let contents = try String(contentsOf: url, encoding: .utf8)