I have a video that is captured with AVCapture, and I'm trying to upload with AFNetworking with Swift.
Code:
let manager = AFHTTPRequestOperationManager()
let url = "http://localhost/test/upload.php"
var fileURL = NSURL.fileURLWithPath(string: ViewControllerVideoPath)
var params = [
"familyId":locationd,
"contentBody" : "Some body content for the test application",
"name" : "the name/title",
"typeOfContent":"photo"
]
manager.POST( url, parameters: params,
constructingBodyWithBlock: { (data: AFMultipartFormData!) in
println("")
var res = data.appendPartWithFileURL(fileURL, name: "fileToUpload", error: nil)
println("was file added properly to the body? \(res)")
},
success: { (operation: AFHTTPRequestOperation!, responseObject: AnyObject!) in
println("Yes thies was a success")
},
failure: { (operation: AFHTTPRequestOperation!, error: NSError!) in
println("We got an error here.. \(error.localizedDescription)")
})
The code above fails, I keep getting
was file added properly to the body? false"
note that ViewControllerVideoPath is a string containing the location of the video which is:
"/private/var/mobile/Containers/Data/Application/1110EE7A-7572-4092-8045-6EEE1B62949/tmp/movie.mov"
using println().... The code above works when I'm uploading a file included in the directory and using:
var fileURL = NSURL.fileURLWithPath(NSBundle.mainBundle().pathForResource("test_1", ofType: "mov")!)
So definitely my PHP code is fine, and the problem lies with uploading that file saved on the device, what am I doing wrong here?
Comments don't allow a full explanation so here is more info;
NSBundle.mainBundle() refers to a path in the bundle file The path in the simulator differs from that of the application ... this is not what you want. There are a number of "folders" you can access based on your needs (private or sharable/files that can get backed up to the cloud). NSPathUtils.h gives a breakdown of the paths available. In keeping with conventions used by most, you should probably create a private path under your application path by doing something like;
- (NSURL *) applicationPrivateDocumentsDirectory{
NSURL *pathURL = [[self applicationLibraryDirecory]URLByAppendingPathComponent:#"MyApplicationName"];
return pathURL;
}
- (NSURL *) applicationLibraryDirecory{
return [[[NSFileManager defaultManager] URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] lastObject];
}
You can test if it exists, if not, create it ... then store your video files in this path, and pass this to your AVCapture as the location to store the file.
Here are the code that can do following functionality in swift.
1 : Check weather directory exist or not. if not exist then create directory(Directory has given application name) in document directory folder.
2 : Now we have application directory. so all file that from application will write/read in/from this directory.
let file = "file.txt"
let directoryName = “XYZ” // Here “XYZ” is project name.
var error : NSError?
let filemgr = NSFileManager.defaultManager()
let dirPaths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,
.UserDomainMask, true)
let documentsDirectory = dirPaths[0] as! String
var dataPath = documentsDirectory.stringByAppendingPathComponent(directoryName)
if !NSFileManager.defaultManager().fileExistsAtPath(dataPath) {
NSFileManager.defaultManager().createDirectoryAtPath(dataPath, withIntermediateDirectories: false, attributes: nil, error: &error)
} else {
println("not creted or exist")
}
Now we have Directory so only need to write/read data from directory.
how to write file in document directory in swift
let filePath = dataPath.stringByAppendingPathComponent(file);
let text = "some text"
//writing
text.writeToFile(filePath, atomically: false, encoding: NSUTF8StringEncoding, error: nil);
How to read file from document directory.
let filePath = dataPath.stringByAppendingPathComponent(file);
// Read file
let text2 = String(contentsOfFile: filePath, encoding: NSUTF8StringEncoding, error: nil)
Output :
Hope this will help you.
Related
I’m trying to get the names of all files and folders in an iCloud Drive directory:
import Foundation
let fileManager = FileManager.default
let directoryURL = URL(string: "folderPathHere")!
do {
let directoryContents = try fileManager.contentsOfDirectory(at: directoryURL, includingPropertiesForKeys: nil, options: [.skipsSubdirectoryDescendants, .skipsHiddenFiles])
for url in directoryContents {
let fileName = fileManager.displayName(atPath: url.absoluteString)
print(fileName)
}
} catch let error {
let directoryName = fileManager.displayName(atPath: directoryURL.absoluteString)
print("Couldnt get contents of \(directoryName): \(error.localizedDescription)")
}
It appears that any iCloud files that haven’t been downloaded to the device don’t return URLs.
I know I can check if a path contains a ubiquitous item when I already know the path with the code below (even if it isn’t downloaded):
fileManager.isUbiquitousItem(at: writePath)
Is there a way to get the URLs & names of those iCloud files without downloading them first?
The directory URL is a security-scoped URL constructed from bookmark data in case that makes any difference (omitted that code here for clarity).
Thanks
Found the answer. I was skipping hidden files with ".skipsHiddenFiles", but the non-downloaded files are actually hidden files, named: ".fileName.ext.iCloud".
Remove the skips hidden files option now works as expected.
You need to use a NSFileCoordinator to access the directory in iCloud Storage, and then normalize placeholder file names for items that haven't been downloaded yet:
let iCloudDirectoryURL = URL(...)
let fileCoordinator = NSFileCoordinator(filePresenter: nil)
fileCoordinator.coordinate(
readingItemAt: iCloudDirectoryURL,
options: NSFileCoordinator.ReadingOptions(),
error: nil
) { readingURL in
do {
let contents = try FileManager.default.contentsOfDirectory(
at: readingURL, includingPropertiesForKeys: nil
)
for url in contents {
print("\(canonicalURL(url))")
}
} catch {
print("Error listing iCloud directory: '\(error)'")
}
}
func canonicalURL(_ url: URL) -> URL {
let prefix = "."
let suffix = ".icloud"
var fileName = url.lastPathComponent
if fileName.hasPrefix(prefix), fileName.hasSuffix(suffix) {
fileName.removeFirst(prefix.count)
fileName.removeLast(suffix.count)
var result = url.deletingLastPathComponent()
result.append(path: fileName)
return result
} else {
return url
}
}
I have the following code with the results of the print statements in comments beside the statements:
let myImageData = FileManager.default.contents(atPath: myURL.absoluteString)
var mySaveToURL: URL = FileManager.default.url(forUbiquityContainerIdentifier: nil)!
mySaveToURL.appendPathComponent(myURL.pathComponents.last!)
print("mySaveToURL=", mySaveToURL) // mySaveToURL= file:///Users/shinehah/Library/Developer/CoreSimulator/Devices/693D4940-1B91-43E1-B5AD-88E9763046C7/data/Library/Mobile%20Documents/iCloud~us~gnolaum~TrialNotifications/ABF236AE-A6E7-403E-ADC4-5BAA5DC734B3.jpeg
let resultCreateFile = FileManager.default.createFile(atPath: mySaveToURL.absoluteString, contents: myImageData, attributes: nil)
print("resultCreateFile=", resultCreateFile) // resultCreateFile= false
do {
try FileManager.default.copyItem(at: myURL, to: mySaveToURL)
print("copy success!") // copy success!
} catch {
print(error.localizedDescription)
}
As you can see I am not able to successfully execute the createFile() method of FileManager but was able to successfully execute the copyItem() method to the same URL.
What do I check to be able to figure out how to get the createFile() method to work?
The error occurs because you are using the wrong API. To get the path of a file system URL you have to use path.
let resultCreateFile = FileManager.default.createFile(atPath: mySaveToURL.path, contents: myImageData, attributes: nil)
However there is no reason to create the file explicitly. Just copy the other file.
I have an issue with saving/replacing image files to the Documents folder in my app.
In the AppDelegate I have a two properties:
let documentsDirectory: URL = { return FileManager().urls(for: .documentDirectory, in: .userDomainMask).first! }()
let defaultDirectory: URL = { return Bundle.main.bundleURL.appendingPathComponent("DefaultBlocks.bundle", isDirectory: true) }()
It looks like the path is valid, have a log output:
[Verbose] application(:didFinishLaunchingWithOptions:) > Docs URL:
file:///var/mobile/Containers/Data/Application/6ED04DA7-077F-4AE2-AB74-2EED02932823/Documents/
[Verbose] application(:didFinishLaunchingWithOptions:) > Defaults URL: file:///var/containers/Bundle/Application/A11D6A4A-E108-483F-86EC-BBFA10E77F72/TheAwesomeApp.app/DefaultBlocks.bundle/
My app logic is: if user requested to reload default images, then replace images in the Documents folder with the reference copies from the app bundle.
I try to implement replacement in the code (called from didFinishLaunchingWithOptions):
func ReloadDefaults() {
let fileManager = FileManager.default
do {
let destDirURL = appDelegate.documentsDirectory
let defaultURLs = Bundle.main.urls(forResourcesWithExtension: "png", subdirectory: "DefaultBlocks.bundle/_default_images_")
for url in defaultURLs! {
let destURL: URL = destDirURL.appendingPathComponent(url.lastPathComponent)
log.verbose("Src URL: \(url)")
log.verbose("Dest URL: \(destURL)")
_ = try fileManager.replaceItemAt(destURL, withItemAt: url.absoluteURL)
}
}
catch {
log.error("File copy error: \(error.localizedDescription)")
}
}
[Verbose] ReloadDefaults() > Src URL: image-512.png --
file:///var/containers/Bundle/Application/A11D6A4A-E108-483F-86EC-BBFA10E77F72/TheAwesomeApp.app/DefaultBlocks.bundle/_default_images_/
[Verbose] ReloadDefaults() > Dest URL:
file:///var/mobile/Containers/Data/Application/6ED04DA7-077F-4AE2-AB74-2EED02932823/Documents/image-512.png
Unfortunately I've got a error for the replaceItemAt call:
[Error] ReloadDefaults() > File copy error: You don’t have permission
to save the file “image-512.png” in the folder “Documents”.
I have a recent versions of the Xcode and iOS.
I want to write log file at my extension, and read it at my app.
For this purpose, I'm using shared groups (so both the app and the extension would be able to read from the same file)
I wrote the following code:
Extension:
let fileManager = NSFileManager.defaultManager()
let containerUrl = fileManager.containerURLForSecurityApplicationGroupIdentifier("group.MyCompany.MyProj")
let extensionLogDirectory = containerUrl?.path?.stringByAppendingString("AppExtensionLogs")
let logFileManager = DDLogFileManagerDefault(logsDirectory: extensionLogDirectory)
PacketTunnelProvider.fileLogger = DDFileLogger(logFileManager: logFileManager)
PacketTunnelProvider.fileLogger!.rollingFrequency = 60*60*12
PacketTunnelProvider.fileLogger!.logFileManager.maximumNumberOfLogFiles = 1
DDLog.addLogger(PacketTunnelProvider.fileLogger)
App (just to read the log file):
let fileManager = NSFileManager.defaultManager()
let containerUrl = fileManager.containerURLForSecurityApplicationGroupIdentifier("group.MyCompany.MyProj")
if let extensionLogDirectory = containerUrl?.path?.stringByAppendingString("AppExtensionLogs") {
do {
let directoryContents = try fileManager.contentsOfDirectoryAtPath(extensionLogDirectory)//always fails
for file in directoryContents {
let path = extensionLogDirectory.stringByAppendingString(file)
do {
let fileContents = try NSString(contentsOfFile: path, encoding: NSUTF8StringEncoding)
NSLog("file: \(fileContents)")
}
catch {/* error handling here */
}
}
}
catch {/* error handling here */
NSLog("nope!")
}
But, something now right - it's seems like contentsOfDirectoryAtPath always fails with "no such file" error
What's wrong in this code?
The problem is unrelated to app extensions or CocoaLumberjack.
stringByAppendingString just concatenates strings, so that the path
separator "/" is missing in the generated directory name.
There was a dedicated method stringByAppendingPathComponent, which however
has been deprecated in Objective-C and is no longer available in Swift.
You should operate on the URL by using URLByAppendingPathComponent
instead:
let extensionLogDirectory = containerUrl?.URLByAppendingPathComponent("AppExtensionLogs").path
I have the following sqllite code:
func createAndCheckDatabase()-> Bool
{
var success: Bool = true
var db:COpaquePointer = nil // Get path to DB in Documents directory
let docDir:AnyObject = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
let path = docDir.stringByAppendingPathComponent("MyDatabase.db")
// Check if copy of DB is there in Documents directory
let fm = NSFileManager.defaultManager()
if !(fm.fileExistsAtPath(path)) {
// The database does not exist, so copy to Documents directory
let from = NSBundle.mainBundle().resourcePath!.stringByAppendingPathComponent(databaseName)
var error:NSError?
if !fm.copyItemAtPath(from, toPath: path, error: &error) {
//ALWAYS ERRORS HERE THE FIRST TIME
println("SQLiteDB - #1 failed to open DB.")
println("Error - \(error!.localizedDescription)")
}
}
databasePath = path
// Open the DB
let cpath = (path as NSString).UTF8String
let error = sqlite3_open(cpath, &db)
if error != SQLITE_OK {
// Open failed, close DB and fail
println("SQLiteDB - another error - couldn't open DB")
sqlite3_close(db)
}
return success
}
I call this function within my app delegate with the thought that it would successfully create my database once (and only once). Whenever I clear settings and run it, it always hits the area I've marked (error) once. After running it again I never get this error anymore.
Is there some logic flaw in this code (I mostly copied this code) or am I perhaps reporting an error that is actually not? I suspect that it might just be happening the first time it creates, but i'm actually OK and can start interacting with the database just fine.
Also does anyone sees something concerning in the code?
Thanks!
Well, after not really figuring out why the above code cobbled together from online tutorials did as I described, I found a very helpful article here:
http://metrozines.com
This ended up solving my problem (by following how they did things and introducing the code from the tutorial). Now when I clear settings, it doesn't crash and starting it up again works correctly without throwing an error.
The code that works now is this:
func createAndCheckDatabase() -> Bool {
let DATABASE_RESOURCE_NAME = "abc"
let DATABASE_RESOURCE_TYPE = "sqlite"
let DATABASE_FILE_NAME = "abc.sqlite"
let documentFolderPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let dbfile = "/" + DATABASE_FILE_NAME;
self.dbFilePath = documentFolderPath.stringByAppendingString(dbfile)
let filemanager = NSFileManager.defaultManager()
if (!filemanager.fileExistsAtPath(dbFilePath) ) {
let backupDbPath = NSBundle.mainBundle().pathForResource(DATABASE_RESOURCE_NAME, ofType: DATABASE_RESOURCE_TYPE)
if (backupDbPath == nil) {
return false
} else {
var error: NSError?
let copySuccessful = filemanager.copyItemAtPath(backupDbPath!, toPath:dbFilePath, error: &error)
if !copySuccessful {
println("copy failed: \(error?.localizedDescription)")
return false
}
}
}
return true
}