While the following code should have ensured that the call to copyItem would succeed, throwing the error allowed me to see that there is still some situations were there is an existing file at the destination. As such, the new implementation below first creates a folder using a UUID, ensuring that the destination is unique every time.
if FileManager.default.fileExists(atPath: destination.path) {
try FileManager.default.removeItem(at: destination)
}
Here is the complete version of the transfer function.
static func transfer(from received: ReceivedTransferredFile) throws -> Video {
do {
// note: it was necessary to create a folder with a uuidString to ensure that copying the file would not fail even though existing files are removed.
let directory = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true)
try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true, attributes: nil)
let destination = directory.appendingPathComponent(received.file.lastPathComponent)
if FileManager.default.fileExists(atPath: destination.path) {
try FileManager.default.removeItem(at: destination)
}
try FileManager.default.copyItem(at: received.file, to: destination)
return Video(url: destination, filename: received.file.lastPathComponent)
} catch {
debugPrint("error transferring file: \(error)")
throw error
}
}
While there are other approaches, the use of uuidString only has a minimal impact on the size of the temporary data and it ensures that the destination is unique.