diff --git a/lib/classes/StudipController.php b/lib/classes/StudipController.php
index 33b7e38de3328e3041899e08cfd793cca9bf42b0..e0cfd0584c8ba8b02961fe5d112045e6bbda8721 100644
--- a/lib/classes/StudipController.php
+++ b/lib/classes/StudipController.php
@@ -477,22 +477,21 @@ abstract class StudipController extends Trails\Controller
 
     /**
      * Renders a file
-     * @param string  $file                Path of the file to render
-     * @param string  $filename            Name of the file displayed to user
+     *
+     * @param string       $file                Path of the file to render
+     * @param string|null  $filename            Name of the file displayed to user
      *                                     (will equal $file when missing)
-     * @param string  $content_type        Optional content type (will be determined if missing)
-     * @param string  $content_disposition Either attachment (default) or inline
-     * @param Closure $callback            Optional callback when download has finished
-     * @param int     $chunk_size          Optional size of chunks to send (default: 256k)
+     * @param string|null  $content_type        Optional content type (will be determined if missing)
+     * @param string       $content_disposition Either attachment (default) or inline
+     * @param Closure|null $callback            Optional callback when download has finished
      */
     public function render_file(
-        $file,
-        $filename = null,
-        $content_type = null,
-        $content_disposition = 'attachment',
-        Closure $callback = null,
-        $chunk_size = 262144
-    ) {
+        string   $file,
+        ?string  $filename = null,
+        ?string  $content_type = null,
+        string   $content_disposition = 'attachment',
+        ?Closure $callback = null
+    ): void {
         if (!file_exists($file)) {
             throw new Trails\Exception(404);
         }
@@ -524,19 +523,16 @@ abstract class StudipController extends Trails\Controller
         $this->response->add_header('Content-Length', filesize($file));
         $this->response->add_header('Content-Transfer-Encoding',  'binary');
         $this->response->add_header('Pragma', 'public');
-        $this->render_text(function () use ($file, $chunk_size, $callback) {
-            $fp = fopen($file, 'rb');
-
-            while (!feof($fp)) {
-                yield fgets($fp, $chunk_size);
-            }
 
-            fclose($fp);
+        $this->render_text(
+            app(Psr\Http\Message\StreamFactoryInterface::class)->createStreamFromFile($file)
+        );
 
-            if ($callback) {
+        if ($callback) {
+            NotificationCenter::on('SLIM_AFTER_RUN', function () use ($callback, $file) {
                 $callback($file);
-            }
-        });
+            });
+        }
     }
 
     /**
@@ -544,23 +540,20 @@ abstract class StudipController extends Trails\Controller
      * This is just a convenience method so you don't have to write the delete
      * callback.
      *
-     * @param string  $file                Path of the file to render
-     * @param string  $filename            Name of the file displayed to user
+     * @param string       $file                Path of the file to render
+     * @param string|null  $filename            Name of the file displayed to user
      *                                     (will equal $file when missing)
-     * @param string  $content_type        Optional content type (will be determined if missing)
-     * @param string  $content_disposition Either attachment (default) or inline
-     * @param Closure $callback            Optional callback when download has finished
-     * @param int     $chunk_size          Optional size of chunks to send (default: 256k)
+     * @param string|null  $content_type        Optional content type (will be determined if missing)
+     * @param string       $content_disposition Either attachment (default) or inline
+     * @param Closure|null $callback            Optional callback when download has finished
      */
     public function render_temporary_file(
-        $file,
-        $filename = null,
-        $content_type = null,
-        $content_disposition = 'attachment',
-        Closure $callback = null,
-        $chunk_size = 262144
-
-    ) {
+        string   $file,
+        ?string  $filename = null,
+        ?string  $content_type = null,
+        string   $content_disposition = 'attachment',
+        ?Closure $callback = null
+    ): void {
         $delete_callback = function ($file) use ($callback) {
             unlink($file);
 
@@ -574,8 +567,7 @@ abstract class StudipController extends Trails\Controller
             $filename,
             $content_type,
             $content_disposition,
-            $delete_callback,
-            $chunk_size
+            $delete_callback
         );
     }
 
diff --git a/lib/classes/StudipDispatcher.php b/lib/classes/StudipDispatcher.php
index ea66c1c718e1d18ef26d77dc25879d319194bb3c..10799c7070bfd2b3325c29a20ea9ac09d9307ad1 100644
--- a/lib/classes/StudipDispatcher.php
+++ b/lib/classes/StudipDispatcher.php
@@ -95,7 +95,11 @@ class StudipDispatcher extends Trails\Dispatcher
         $uri = $this->clean_request_uri((string) $uri);
         [$controller_path, $unconsumed] = '' === $uri ? $this->default_route() : $this->parse($uri);
         $controller = $this->load_controller($controller_path);
-        return function ($request, $response, array $args) use ($controller, $unconsumed) {
+        return function (
+            \Psr\Http\Message\ServerRequestInterface $request,
+            \Psr\Http\Message\ResponseInterface $response,
+            array $args
+        ) use ($controller, $unconsumed): \Psr\Http\Message\ResponseInterface {
             $controller->injectResponse($response);
             $response = $controller->perform($unconsumed);
             return $response->getPsrResponse();
diff --git a/public/dispatch.php b/public/dispatch.php
index 8bc346df8be84175455cbe60ba64585149ae4195..c5c2b93c88c78cb5fb9bae1fe513d05a41e59eeb 100644
--- a/public/dispatch.php
+++ b/public/dispatch.php
@@ -33,3 +33,4 @@ $route_callable = $studip_dispatcher->getRouteCallable(Request::pathInfo());
 $app->any(Request::pathInfo(), $route_callable);
 NotificationCenter::postNotification('SLIM_BEFORE_RUN', $app);
 $app->run();
+NotificationCenter::postNotification('SLIM_AFTER_RUN', $app);
diff --git a/public/plugins.php b/public/plugins.php
index 0edb9957f76bc096d222e1b20521e0b04e81f433..46c16795dc976fddfaa7b0bef005f0511a5a2e73 100644
--- a/public/plugins.php
+++ b/public/plugins.php
@@ -70,3 +70,4 @@ $app->add(app(Studip\Middleware\SessionMiddleware::class));
 
 NotificationCenter::postNotification('SLIM_BEFORE_RUN', $app);
 $app->run();
+NotificationCenter::postNotification('SLIM_AFTER_RUN', $app);