diff --git a/Sources/Vapor/Utilities/FileIO.swift b/Sources/Vapor/Utilities/FileIO.swift index 0f8c324ffa..332e6b59fd 100644 --- a/Sources/Vapor/Utilities/FileIO.swift +++ b/Sources/Vapor/Utilities/FileIO.swift @@ -186,4 +186,26 @@ public struct FileIO { return self.request.eventLoop.makeFailedFuture(error) } } + + /// Write the contents of buffer to a file at the supplied path. + /// + /// let data = ByteBuffer(string: "ByteBuffer") + /// try req.fileio.writeFile(data, at: "/path/to/file.txt").wait() + /// + /// - parameters: + /// - path: Path to file on the disk. + /// - buffer: The `ByteBuffer` to write. + /// - returns: `Future` that will complete when the file write is finished. + public func writeFile(_ buffer: ByteBuffer, at path: String) -> EventLoopFuture { + do { + let fd = try NIOFileHandle(path: path, mode: .write, flags: .allowFileCreation()) + let done = io.write(fileHandle: fd, buffer: buffer, eventLoop: self.request.eventLoop) + done.whenComplete { _ in + try? fd.close() + } + return done + } catch { + return self.request.eventLoop.makeFailedFuture(error) + } + } } diff --git a/Tests/VaporTests/FileTests.swift b/Tests/VaporTests/FileTests.swift index c014b5eb63..be9a1a9bb5 100644 --- a/Tests/VaporTests/FileTests.swift +++ b/Tests/VaporTests/FileTests.swift @@ -32,6 +32,22 @@ final class FileTests: XCTestCase { XCTAssertContains(res.body.string, test) } } + + func testFileWrite() throws { + let app = Application(.testing) + defer { app.shutdown() } + + let request = Request(application: app, on: app.eventLoopGroup.next()) + + let data = "Hello" + let path = "/tmp/fileio_write.txt" + + try request.fileio.writeFile(ByteBuffer(string: data), at: path).wait() + defer { try? FileManager.default.removeItem(atPath: path) } + + let result = try String(contentsOfFile: path) + XCTAssertEqual(result, data) + } func testPercentDecodedFilePath() throws { let app = Application(.testing)