My app has a custom file type, and I'm trying to update my code so that when I export or import a file that has a "/" character in the name. Currently the app just fails to export a file when it has that character in the name.
This is what I have for exporting the file:
static func exportDocument(_ document: StitchDocument) async -> SentTransferredFile {
log("StitchDocumentWrapper: transferRepresentation: exporting: called")
let projectURL = document.getUrl()
// Use the original document name (which may contain '/') for the exported file
let exportedFileName = document.name + ".stitch"
// Create the temporary export URL in the temporary directory
let tempExportURL = StitchFileManager.tempDir.appendingPathComponent(exportedFileName)
log("StitchDocumentWrapper: transferRepresentation: projectURL: \(projectURL)")
log("StitchDocumentWrapper: transferRepresentation: tempExportURL: \(tempExportURL)")
do {
// Remove any existing file at the temp export URL
try? FileManager.default.removeItem(at: tempExportURL)
// Zip existing project url's contents to the temp export URL
try FileManager.default.zipItem(at: projectURL, to: tempExportURL)
// Return the SentTransferredFile with the temp file URL
return SentTransferredFile(tempExportURL)
} catch {
log("StitchDocumentWrapper: transferRepresentation: FAILED: error: \(error)")
// In case of error, still try to return a file, but it might not contain the correct data
return SentTransferredFile(tempExportURL)
}
}
Note that StitchFileManager
is a sub-class of FileManager
.
The specific problem is that when the file is exported, it always creates additional directories. So, a file named 1/2/3.stitch
would create a file at the following directory:
file:///Users/nicholasarner/Library/Containers/app.stitchdesign.stitch/Data/tmp/1/2/3.stitch
I need to figure out how preserve the file name without creating additional directories due to the inclusion of the / characters.
Forward slashes are simply not allowed in file names.
The user can give a file a name that contains /
in the Files app and other places, because under the hood, the /
is getting converted to a :
. You can do the same in your app too.
let exportedFileName = (document.name + ".stitch").replacingOccurrences(of: "/", with: ":")
The Files app and others will replace the :
with /
when displaying the file names, so it still looks like the file name has a /
to the user.
As a concrete example, here is a view that shares a file named "Foo:Bar.txt".
struct ContentView: View {
var body: some View {
let url = URL.documentsDirectory.appendingPathComponent("Foo:Bar.txt")
ShareLink(item: url)
.onAppear {
FileManager.default.createFile(atPath: url.path(), contents: nil)
}
}
}
After activating the share link, the share sheet shows the file name as "File/Bar":