diff --git a/src/database.rs b/src/database.rs
index 2870e2d1e572fe9ce7a643611cc4e53dc215d2d8..fa84881d95657323df6b85866803200a346d8687 100644
--- a/src/database.rs
+++ b/src/database.rs
@@ -20,11 +20,7 @@
 use rocket::futures::{channel::mpsc, stream::FuturesUnordered, StreamExt};
 use ruma::{DeviceId, ServerName, UserId};
 use serde::Deserialize;
-use std::{
-    collections::HashMap,
-    fs::remove_dir_all,
-    sync::{Arc, RwLock},
-};
+use std::{collections::HashMap, fs::{self, remove_dir_all}, io::Write, sync::{Arc, RwLock}};
 use tokio::sync::Semaphore;
 
 #[derive(Clone, Debug, Deserialize)]
@@ -253,9 +249,11 @@ pub async fn load_or_create(config: Config) -> Result<Arc<Self>> {
             for (userid, password) in db.users.userid_password.iter() {
                 let password = utils::string_from_bytes(&password);
 
-                if password.map_or(false, |password| {
+                let empty_hashed_password = password.map_or(false, |password| {
                     argon2::verify_encoded(&password, b"").unwrap_or(false)
-                }) {
+                });
+
+                if empty_hashed_password {
                     db.users.userid_password.insert(&userid, b"")?;
                 }
             }
@@ -265,6 +263,23 @@ pub async fn load_or_create(config: Config) -> Result<Arc<Self>> {
             println!("Migration: 1 -> 2 finished");
         }
 
+        if db.globals.database_version()? < 3 {
+            // Move media to filesystem
+            for (key, content) in db.media.mediaid_file.iter() {
+                if content.len() == 0 {
+                    continue;
+                }
+
+                let path = db.globals.get_media_file(&key);
+                let mut file = fs::File::create(path)?;
+                file.write_all(&content)?;
+                db.media.mediaid_file.insert(&key, &[])?;
+            }
+
+            db.globals.bump_database_version(3)?;
+
+            println!("Migration: 2 -> 3 finished");
+        }
         // This data is probably outdated
         db.rooms.edus.presenceid_presence.clear()?;
 
diff --git a/src/database/media.rs b/src/database/media.rs
index b81e86333909bc4e8c2dc7f4baa6c8c945482bd8..944c5bdce1124e1220e478a997880f43fa4a3a1e 100644
--- a/src/database/media.rs
+++ b/src/database/media.rs
@@ -103,7 +103,7 @@ pub async fn get(&self, globals: &Globals, mxc: &str) -> Result<Option<FileMeta>
         let mut iter = self.mediaid_file.scan_prefix(prefix);
         if let Some((key, _)) = iter.next() {
             let path = globals.get_media_file(&key);
-            let mut file = vec![];
+            let mut file = Vec::new();
             File::open(path).await?.read_to_end(&mut file).await?;
             let mut parts = key.rsplit(|&b| b == 0xff);
 
@@ -192,7 +192,7 @@ pub async fn get_thumbnail(
         if let Some((key, _)) = self.mediaid_file.scan_prefix(thumbnail_prefix).next() {
             // Using saved thumbnail
             let path = globals.get_media_file(&key);
-            let mut file = vec![];
+            let mut file = Vec::new();
             File::open(path).await?.read_to_end(&mut file).await?;
             let mut parts = key.rsplit(|&b| b == 0xff);
 
@@ -227,7 +227,7 @@ pub async fn get_thumbnail(
         } else if let Some((key, _)) = self.mediaid_file.scan_prefix(original_prefix).next() {
             // Generate a thumbnail
             let path = globals.get_media_file(&key);
-            let mut file = vec![];
+            let mut file = Vec::new();
             File::open(path).await?.read_to_end(&mut file).await?;
 
             let mut parts = key.rsplit(|&b| b == 0xff);