diff --git a/lib/private/Files/Node/Folder.php b/lib/private/Files/Node/Folder.php
index 1267c81866834d0b3d91d666fdd3402835563d79..727b08e9335f762735ec6c91b49f6fb7b11e363b 100644
--- a/lib/private/Files/Node/Folder.php
+++ b/lib/private/Files/Node/Folder.php
@@ -173,15 +173,21 @@ class Folder extends Node implements \OCP\Files\Folder {
 
 	/**
 	 * @param string $path
+	 * @param string | resource | null $content
 	 * @return \OC\Files\Node\File
 	 * @throws \OCP\Files\NotPermittedException
 	 */
-	public function newFile($path) {
+	public function newFile($path, $content = null) {
 		if ($this->checkPermissions(\OCP\Constants::PERMISSION_CREATE)) {
 			$fullPath = $this->getFullPath($path);
 			$nonExisting = new NonExistingFile($this->root, $this->view, $fullPath);
 			$this->sendHooks(['preWrite', 'preCreate'], [$nonExisting]);
-			if (!$this->view->touch($fullPath)) {
+			if ($content !== null) {
+				$result = $this->view->file_put_contents($fullPath, $content);
+			} else {
+				$result = $this->view->touch($fullPath);
+			}
+			if (!$result) {
 				throw new NotPermittedException('Could not create path');
 			}
 			$node = new File($this->root, $this->view, $fullPath);
diff --git a/lib/private/Files/Node/LazyRoot.php b/lib/private/Files/Node/LazyRoot.php
index 76868cfa5cdb3bb4976eba1c07f631b423535388..8076c3b4f6abefa163b6d4320930c5b4d7ccb12f 100644
--- a/lib/private/Files/Node/LazyRoot.php
+++ b/lib/private/Files/Node/LazyRoot.php
@@ -394,7 +394,7 @@ class LazyRoot implements IRootFolder {
 	/**
 	 * @inheritDoc
 	 */
-	public function newFile($path) {
+	public function newFile($path, $content = null) {
 		return $this->__call(__FUNCTION__, func_get_args());
 	}
 
diff --git a/lib/private/Files/Node/NonExistingFolder.php b/lib/private/Files/Node/NonExistingFolder.php
index 30470740495ca5f17d563fb4fd6c8f1ff5a584ac..65af837da43bded77fcb787692051f10896fe8e4 100644
--- a/lib/private/Files/Node/NonExistingFolder.php
+++ b/lib/private/Files/Node/NonExistingFolder.php
@@ -139,7 +139,7 @@ class NonExistingFolder extends Folder {
 		throw new NotFoundException();
 	}
 
-	public function newFile($path) {
+	public function newFile($path, $content = null) {
 		throw new NotFoundException();
 	}
 
diff --git a/lib/private/Files/SimpleFS/NewSimpleFile.php b/lib/private/Files/SimpleFS/NewSimpleFile.php
new file mode 100644
index 0000000000000000000000000000000000000000..02dde1d2f883dfe6316f9f1ddfb3f79b978fb755
--- /dev/null
+++ b/lib/private/Files/SimpleFS/NewSimpleFile.php
@@ -0,0 +1,221 @@
+<?php declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2020 Robin Appelman <robin@icewind.nl>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Files\SimpleFS;
+
+use Icewind\Streams\CallbackWrapper;
+use OCP\Files\File;
+use OCP\Files\Folder;
+use OCP\Files\NotFoundException;
+use OCP\Files\NotPermittedException;
+use OCP\Files\SimpleFS\ISimpleFile;
+
+class NewSimpleFile implements ISimpleFile {
+	private $parentFolder;
+	private $name;
+	/** @var File|null */
+	private $file = null;
+
+	/**
+	 * File constructor.
+	 *
+	 * @param File $file
+	 */
+	public function __construct(Folder $parentFolder, string $name) {
+		$this->parentFolder = $parentFolder;
+		$this->name = $name;
+	}
+
+	/**
+	 * Get the name
+	 *
+	 * @return string
+	 */
+	public function getName() {
+		return $this->name;
+	}
+
+	/**
+	 * Get the size in bytes
+	 *
+	 * @return int
+	 */
+	public function getSize() {
+		if ($this->file) {
+			return $this->file->getSize();
+		} else {
+			return 0;
+		}
+	}
+
+	/**
+	 * Get the ETag
+	 *
+	 * @return string
+	 */
+	public function getETag() {
+		if ($this->file) {
+			return $this->file->getEtag();
+		} else {
+			return '';
+		}
+	}
+
+	/**
+	 * Get the last modification time
+	 *
+	 * @return int
+	 */
+	public function getMTime() {
+		if ($this->file) {
+			return $this->file->getMTime();
+		} else {
+			return time();
+		}
+	}
+
+	/**
+	 * Get the content
+	 *
+	 * @return string
+	 * @throws NotFoundException
+	 * @throws NotPermittedException
+	 */
+	public function getContent() {
+		if ($this->file) {
+			$result = $this->file->getContent();
+
+			if ($result === false) {
+				$this->checkFile();
+			}
+
+			return $result;
+		} else {
+			return '';
+		}
+	}
+
+	/**
+	 * Overwrite the file
+	 *
+	 * @param string|resource $data
+	 * @throws NotPermittedException
+	 * @throws NotFoundException
+	 */
+	public function putContent($data) {
+		try {
+			if ($this->file) {
+				return $this->file->putContent($data);
+			} else {
+				$this->file = $this->parentFolder->newFile($this->name, $data);
+			}
+		} catch (NotFoundException $e) {
+			$this->checkFile();
+		}
+	}
+
+	/**
+	 * Sometimes there are some issues with the AppData. Most of them are from
+	 * user error. But we should handle them gracefull anyway.
+	 *
+	 * If for some reason the current file can't be found. We remove it.
+	 * Then traverse up and check all folders if they exists. This so that the
+	 * next request will have a valid appdata structure again.
+	 *
+	 * @throws NotFoundException
+	 */
+	private function checkFile() {
+		$cur = $this->file;
+
+		while ($cur->stat() === false) {
+			$parent = $cur->getParent();
+			try {
+				$cur->delete();
+			} catch (NotFoundException $e) {
+				// Just continue then
+			}
+			$cur = $parent;
+		}
+
+		if ($cur !== $this->file) {
+			throw new NotFoundException('File does not exist');
+		}
+	}
+
+
+	/**
+	 * Delete the file
+	 *
+	 * @throws NotPermittedException
+	 */
+	public function delete() {
+		if ($this->file) {
+			$this->file->delete();
+		}
+	}
+
+	/**
+	 * Get the MimeType
+	 *
+	 * @return string
+	 */
+	public function getMimeType() {
+		if ($this->file) {
+			return $this->file->getMimeType();
+		} else {
+			return 'text/plain';
+		}
+	}
+
+	/**
+	 * Open the file as stream for reading, resulting resource can be operated as stream like the result from php's own fopen
+	 *
+	 * @return resource
+	 * @throws \OCP\Files\NotPermittedException
+	 * @since 14.0.0
+	 */
+	public function read() {
+		if ($this->file) {
+			return $this->file->fopen('r');
+		} else {
+			return fopen('php://temp', 'r');
+		}
+	}
+
+	/**
+	 * Open the file as stream for writing, resulting resource can be operated as stream like the result from php's own fopen
+	 *
+	 * @return resource
+	 * @throws \OCP\Files\NotPermittedException
+	 * @since 14.0.0
+	 */
+	public function write() {
+		if ($this->file) {
+			return $this->file->fopen('w');
+		} else {
+			$source = fopen('php://temp', 'w+');
+			return CallbackWrapper::wrap($source, null, null, null, null, function () use ($source) {
+				rewind($source);
+				$this->putContent($source);
+			});
+		}
+	}
+}
diff --git a/lib/private/Files/SimpleFS/SimpleFolder.php b/lib/private/Files/SimpleFS/SimpleFolder.php
index 833aa7d76cfd988e8a86a282699bcdd6dcf074d0..76f6a198e2520c5f770ae195c24221a6b8bc01c0 100644
--- a/lib/private/Files/SimpleFS/SimpleFolder.php
+++ b/lib/private/Files/SimpleFS/SimpleFolder.php
@@ -81,8 +81,7 @@ class SimpleFolder implements ISimpleFolder   {
 	}
 
 	public function newFile($name) {
-		$file = $this->folder->newFile($name);
-
-		return new SimpleFile($file);
+		// delay creating the file until it's written to
+		return new NewSimpleFile($this->folder, $name);
 	}
 }
diff --git a/lib/public/Files/Folder.php b/lib/public/Files/Folder.php
index 99d331850cfeebc7885e66404441e10da3bda342..e7286ea028c32d755cfa5381aed34500c0ab698c 100644
--- a/lib/public/Files/Folder.php
+++ b/lib/public/Files/Folder.php
@@ -109,11 +109,12 @@ interface Folder extends Node {
 	 * Create a new file
 	 *
 	 * @param string $path relative path of the new file
+	 * @param string | resource | null $content content for the new file, since 19.0.0
 	 * @return \OCP\Files\File
 	 * @throws \OCP\Files\NotPermittedException
 	 * @since 6.0.0
 	 */
-	public function newFile($path);
+	public function newFile($path, $content = null);
 
 	/**
 	 * search for files with the name matching $query