diff --git a/libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino b/libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino
index fb5847d4b0..bd25fad582 100644
--- a/libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino
+++ b/libraries/ESP8266WebServer/examples/FSBrowser/FSBrowser.ino
@@ -186,12 +186,27 @@ void handleFileList() {
   Dir dir = filesystem->openDir(path);
   path.clear();
 
-  String output = "[";
+  // use HTTP/1.1 Chunked response to avoid building a huge temporary string
+  if (!server.chunkedResponseModeStart(200, "text/json")) {
+    server.send(505, FPSTR("text/html"), FPSTR("HTTP1.1 required"));
+    return;
+  }
+
+  // use the same string for every line
+  String output;
+  output.reserve(64);
   while (dir.next()) {
-    File entry = dir.openFile("r");
-    if (output != "[") {
-      output += ',';
+
+    if (output.length()) {
+      // send string from previous iteration
+      // as an HTTP chunk
+      server.sendContent(output);
+      output = ',';
+    } else {
+      output = '[';
     }
+
+    File entry = dir.openFile("r");
     bool isDir = false;
     output += "{\"type\":\"";
     output += (isDir) ? "dir" : "file";
@@ -205,8 +220,10 @@ void handleFileList() {
     entry.close();
   }
 
+  // send last string
   output += "]";
-  server.send(200, "text/json", output);
+  server.sendContent(output);
+  server.chunkedResponseFinalize();
 }
 
 void setup(void) {
diff --git a/libraries/ESP8266WebServer/src/ESP8266WebServer.h b/libraries/ESP8266WebServer/src/ESP8266WebServer.h
index eefcba2ba3..9e999acadc 100644
--- a/libraries/ESP8266WebServer/src/ESP8266WebServer.h
+++ b/libraries/ESP8266WebServer/src/ESP8266WebServer.h
@@ -149,18 +149,36 @@ class ESP8266WebServerTemplate
   void sendContent(const char *content) { sendContent_P(content); }
   void sendContent(const char *content, size_t size) { sendContent_P(content, size); }
 
+  bool chunkedResponseModeStart_P (int code, PGM_P content_type) {
+    if (_currentVersion == 0)
+        // no chunk mode in HTTP/1.0
+        return false;
+    setContentLength(CONTENT_LENGTH_UNKNOWN);
+    send_P(code, content_type, "");
+    return true;
+  }
+  bool chunkedResponseModeStart (int code, const char* content_type) {
+    return chunkedResponseModeStart_P(code, content_type);
+  }
+  bool chunkedResponseModeStart (int code, const String& content_type) {
+    return chunkedResponseModeStart_P(code, content_type.c_str());
+  }
+  void chunkedResponseFinalize () {
+    sendContent(emptyString);
+  }
+
   static String credentialHash(const String& username, const String& realm, const String& password);
 
   static String urlDecode(const String& text);
 
-  // Handle a GET request by sending a response header and stream file content to response body 
+  // Handle a GET request by sending a response header and stream file content to response body
   template<typename T>
   size_t streamFile(T &file, const String& contentType) {
     return streamFile(file, contentType, HTTP_GET);
   }
 
   // Implement GET and HEAD requests for files.
-  // Stream body on HTTP_GET but not on HTTP_HEAD requests. 
+  // Stream body on HTTP_GET but not on HTTP_HEAD requests.
   template<typename T>
   size_t streamFile(T &file, const String& contentType, HTTPMethod requestMethod) {
     size_t contentLength = 0;