fileManager.copyItem(atPath, toPath) - File exists. But it doesnt [duplicate] - swift

I'm building a simple program in Swift, it should copy files with a certain extension to a different folder. If this folder exist the program will just copy them in the folder, if the folder doesn't exist, the program has to make it first.
let newMTSFolder = folderPath.stringByAppendingPathComponent("MTS Files")
if (!fileManager.fileExistsAtPath(newMTSFolder)) {
fileManager.createDirectoryAtPath(newMTSFolder, withIntermediateDirectories: false, attributes: nil, error: nil)
}
while let element = enumerator.nextObject() as? String {
if element.hasSuffix("MTS") { // checks the extension
var fullElementPath = folderPath.stringByAppendingPathComponent(element)
println("copy \(fullElementPath) to \(newMTSFolder)")
var err: NSError?
if NSFileManager.defaultManager().copyItemAtPath(fullElementPath, toPath: newMTSFolder, error: &err) {
println("\(fullElementPath) file added to the folder.")
} else {
println("FAILED to add \(fullElementPath) to the folder.")
}
}
}
Running this code will correctly identify the MTS files but then result in a "FAILED to add...", what am I doing wrong?

From the copyItemAtPath(...) documentation:
dstPath
The path at which to place the copy of srcPath. This path must
include the name of the file or directory in its new location. ...
You have to append the file name to the destination directory for the
copyItemAtPath() call (code updated for Swift 3 and later)
let srcURL = URL(fileURLWithPath: fullElementPath)
let destURL = URL(fileURLWithPath: newMTSFolder).appendingPathComponent(srcURL.lastPathComponent)
do {
try FileManager.default.copyItem(at: srcURL, to: destURL)
} catch {
print("copy failed:", error.localizedDescription)
}

Related

How do I add an Images folder to my FileWrapper

I need a FileWrapper which contains a file and contains a folder.
The file is a single file, and the folder is used to write images to.
The folder also can contain some subfolders. I have a working code, but the issue is that when the Document gets saved, the folder gets re-written which deletes my images and subfolders.
I'm quite sure it has something to do with func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper but I need some help from somebody with more experience with FileWrappers.
This is my code:
struct MyProject: FileDocument {
var myFile: MyFile
static var readableContentTypes: [UTType] { [.myf] }
init(myFile: MyFile = MyFile() {
self.myFile = myFile
}
init(configuration: ReadConfiguration) throws {
let decoder = JSONDecoder()
guard let data = configuration.file.fileWrappers?["MYFProject"]?.regularFileContents else {
throw CocoaError(.fileReadCorruptFile)
}
do {
self.myFile = try decoder.decode(MyFile.self, from: data)
} catch {
throw error
}
}
func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
let encoder = JSONEncoder()
do {
let data = try encoder.encode(myFile)
let mainDirectory = FileWrapper(directoryWithFileWrappers: [:])
let myfWrapper = FileWrapper(regularFileWithContents: data)
let imagesWrapper = FileWrapper(directoryWithFileWrappers: [:])
let imageSubFolder = FileWrapper(directoryWithFileWrappers: [:])
for numberString in myFile.numbers {
imageSubFolder.preferredFilename = numberString
imagesWrapper.addFileWrapper(imageSubFolder)
}
myfWrapper.preferredFilename = "MYFProject"
mainDirectory.addFileWrapper(myfWrapper)
imagesWrapper.preferredFilename = "MYFImages"
mainDirectory.addFileWrapper(imagesWrapper)
return mainDirectory
} catch {
throw error
}
}
}
I use this path to write images to.
func getSubFolderImageFolder(documentPath: URL, subFolder: String) -> URL {
let sfProjectPath = documentPath.appendingPathComponent("MYFImages").appendingPathComponent(subFolder)
if !FileManager.default.fileExists(atPath: sfProjectPath.path) {
do {
try FileManager.default.createDirectory(atPath: sfProjectPath.path, withIntermediateDirectories: false, attributes: nil)
return sfProjectPath
} catch {
fatalError(error.localizedDescription)
}
}
else {
return sfProjectPath
}
}
Thanks in advance!
Your getSubFolderImageFolder function is not going to work well with file wrappers. You must use the FileWrapper methods to create the folders and files in the file wrapper.
To add a subfolder to your images folder, create a directory file wrapper the same way you created the imagesWrapper folder for the images. Add the subfolder as a child of the images folder.
let imageSubFolder = FileWrapper(directoryWithFileWrappers: [:])
imagesWrapper.addFileWrapper(imageSubFolder)
You must create a directory file wrapper for each subfolder. I notice in your updated code, you have only one subfolder file wrapper. With only one subfolder file wrapper, you have no way to store an image file in the correct subfolder.
To add the images, start by converting each image into a Data object. Create a regular file wrapper for each image, passing the image data as the argument to regularFileWithContents. Call addFileWrapper to add the image file to the appropriate folder.
let imageFile = FileWrapper(regularFileWithContents: imageData)
imageFile.preferredFilename = "ImageFilename" // Replace with your filename.
imagesWrapper.addFileWrapper(imageFile)
In your case the image subfolders will call addFileWrapper to add the images. The destination for the image file calls addFileWrapper.
You can find more detailed information about file wrappers in the following article:
Using File Wrappers in a SwiftUI App

Auto create directory when writing a file to a directory that does not exist

I am using File Manager to write files to the users documents directory. Every file is downloaded to a users device via a URL and then I create a local URL by doing the following:
extension URL {
func getLocalUrl() -> URL {
let directoryURL = FileManager.default.getDocumentsDirectory()
let filePath = pathComponents.dropFirst().joined(separator: "-")
return directoryURL.appendingPathComponent(filePath)
}
}
This works perfectly fine. However, when I try to create a local URL by using slashes instead of dashes via the following:
extension URL {
func getLocalUrl() -> URL {
let directoryURL = FileManager.default.getDocumentsDirectory()
let filePath = pathComponents.dropFirst().joined(separator: "/")
return directoryURL.appendingPathComponent(filePath)
}
}
I get the following error when this code runs:
func save(url: URL, fileUrl: URL) {
do {
// fileUrl is a url in the temporary directory from a URLSession.downloadTask
try FileManager.default.moveItem(at: fileUrl, to: url.getLocalUrl())
} catch {
print("download.service.write.error: \(error)")
}
}
CFNetworkDownload_sKaBto.tmp” couldn’t be moved to “user-data” because either the former doesn’t exist, or the folder containing the latter doesn’t exist."
As you can see the error is because I am trying to write to a directory that does not exist. Is there a way to auto create the directory if it does not exist?

How to check if multiple files exist in documents directory? (Swift)

I can check if one file exists with this method:
let fileNameOne = "savedpicture1"
let fileURLOne = documentsDirectoryURL.appendingPathComponent(fileNameOne)
if !FileManager.default.fileExists(atPath: fileURLOne.path) {
removeImage(itemName: "savedpicture1", fileExtension: "jpg")
} else {
print("There was no image to remove")
}
My problem is having to repeat the same lines of code for multiple files. For instance, I would like to check if the files exist in an array of paths, but I would have to repeat the code from above for each file, and it seems too redundant. I'm wondering if there's a way to check multiple files instead of repeating the code for each single path. ".fileExists" only enables me to check one path:
let filePaths = [fileURLOne.path, fileURLTwo.path, fileURLThree.path,
fileURLFour.path]
Write a method for example
func checkFiles(with fileNames: [String] {
for fileName in fileNames {
let fileURL = documentsDirectoryURL.appendingPathComponent(fileName)
if !FileManager.default.fileExists(atPath: fileURL.path) {
removeImage(itemName: fileName, fileExtension: "jpg")
} else {
print("There was no image to remove at", fileURL)
}
}
}
and call it
let fileNames = ["savedpicture1", "savedpicture2", "savedpicture3", "savedpicture4"]
checkFiles(with: fileNames)

copying a file doesn't work [duplicate]

I'm building a simple program in Swift, it should copy files with a certain extension to a different folder. If this folder exist the program will just copy them in the folder, if the folder doesn't exist, the program has to make it first.
let newMTSFolder = folderPath.stringByAppendingPathComponent("MTS Files")
if (!fileManager.fileExistsAtPath(newMTSFolder)) {
fileManager.createDirectoryAtPath(newMTSFolder, withIntermediateDirectories: false, attributes: nil, error: nil)
}
while let element = enumerator.nextObject() as? String {
if element.hasSuffix("MTS") { // checks the extension
var fullElementPath = folderPath.stringByAppendingPathComponent(element)
println("copy \(fullElementPath) to \(newMTSFolder)")
var err: NSError?
if NSFileManager.defaultManager().copyItemAtPath(fullElementPath, toPath: newMTSFolder, error: &err) {
println("\(fullElementPath) file added to the folder.")
} else {
println("FAILED to add \(fullElementPath) to the folder.")
}
}
}
Running this code will correctly identify the MTS files but then result in a "FAILED to add...", what am I doing wrong?
From the copyItemAtPath(...) documentation:
dstPath
The path at which to place the copy of srcPath. This path must
include the name of the file or directory in its new location. ...
You have to append the file name to the destination directory for the
copyItemAtPath() call (code updated for Swift 3 and later)
let srcURL = URL(fileURLWithPath: fullElementPath)
let destURL = URL(fileURLWithPath: newMTSFolder).appendingPathComponent(srcURL.lastPathComponent)
do {
try FileManager.default.copyItem(at: srcURL, to: destURL)
} catch {
print("copy failed:", error.localizedDescription)
}

Swift: failing to copy files to a newly created folder

I'm building a simple program in Swift, it should copy files with a certain extension to a different folder. If this folder exist the program will just copy them in the folder, if the folder doesn't exist, the program has to make it first.
let newMTSFolder = folderPath.stringByAppendingPathComponent("MTS Files")
if (!fileManager.fileExistsAtPath(newMTSFolder)) {
fileManager.createDirectoryAtPath(newMTSFolder, withIntermediateDirectories: false, attributes: nil, error: nil)
}
while let element = enumerator.nextObject() as? String {
if element.hasSuffix("MTS") { // checks the extension
var fullElementPath = folderPath.stringByAppendingPathComponent(element)
println("copy \(fullElementPath) to \(newMTSFolder)")
var err: NSError?
if NSFileManager.defaultManager().copyItemAtPath(fullElementPath, toPath: newMTSFolder, error: &err) {
println("\(fullElementPath) file added to the folder.")
} else {
println("FAILED to add \(fullElementPath) to the folder.")
}
}
}
Running this code will correctly identify the MTS files but then result in a "FAILED to add...", what am I doing wrong?
From the copyItemAtPath(...) documentation:
dstPath
The path at which to place the copy of srcPath. This path must
include the name of the file or directory in its new location. ...
You have to append the file name to the destination directory for the
copyItemAtPath() call (code updated for Swift 3 and later)
let srcURL = URL(fileURLWithPath: fullElementPath)
let destURL = URL(fileURLWithPath: newMTSFolder).appendingPathComponent(srcURL.lastPathComponent)
do {
try FileManager.default.copyItem(at: srcURL, to: destURL)
} catch {
print("copy failed:", error.localizedDescription)
}