diff --git a/src/client/app/admin/views/drive.vue b/src/client/app/admin/views/drive.vue
new file mode 100644
index 0000000000..d543d0a077
--- /dev/null
+++ b/src/client/app/admin/views/drive.vue
@@ -0,0 +1,139 @@
+<template>
+<div class="pwnqwyet">
+	<ui-card>
+		<div slot="title"><fa :icon="faCloud"/> {{ $t('@.drive') }}</div>
+		<section class="fit-top">
+			<ui-horizon-group inputs>
+				<ui-select v-model="sort">
+					<span slot="label">{{ $t('sort.title') }}</span>
+					<option value="-createdAt">{{ $t('sort.createdAtAsc') }}</option>
+					<option value="+createdAt">{{ $t('sort.createdAtDesc') }}</option>
+					<option value="-size">{{ $t('sort.sizeAsc') }}</option>
+					<option value="+size">{{ $t('sort.sizeDesc') }}</option>
+				</ui-select>
+				<ui-select v-model="origin">
+					<span slot="label">{{ $t('origin.title') }}</span>
+					<option value="combined">{{ $t('origin.combined') }}</option>
+					<option value="local">{{ $t('origin.local') }}</option>
+					<option value="remote">{{ $t('origin.remote') }}</option>
+				</ui-select>
+			</ui-horizon-group>
+			<div class="kidvdlkg" v-for="file in files">
+				<div>
+					<div class="thumbnail" :style="thumbnail(file)"></div>
+				</div>
+				<div>
+					<header>
+						<b>{{ file.name }}</b>
+						<span class="username">@{{ file.user | acct }}</span>
+					</header>
+					<div>
+						<div>
+							<span style="margin-right:16px;">{{ file.type }}</span>
+							<span>{{ file.datasize | bytes }}</span>
+						</div>
+						<div><mk-time :time="file.createdAt" mode="detail"/></div>
+					</div>
+				</div>
+			</div>
+			<ui-button v-if="existMore" @click="fetch">{{ $t('@.load-more') }}</ui-button>
+		</section>
+	</ui-card>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import i18n from '../../i18n';
+import { faCloud } from '@fortawesome/free-solid-svg-icons';
+
+export default Vue.extend({
+	i18n: i18n('admin/views/drive.vue'),
+
+	data() {
+		return {
+			sort: '+createdAt',
+			origin: 'combined',
+			limit: 10,
+			offset: 0,
+			files: [],
+			existMore: false,
+			faCloud
+		};
+	},
+
+	watch: {
+		sort() {
+			this.files = [];
+			this.offset = 0;
+			this.fetch();
+		},
+
+		origin() {
+			this.files = [];
+			this.offset = 0;
+			this.fetch();
+		}
+	},
+
+	mounted() {
+		this.fetch();
+	},
+
+	methods: {
+		fetch() {
+			this.$root.api('admin/drive/files', {
+				origin: this.origin,
+				sort: this.sort,
+				offset: this.offset,
+				limit: this.limit + 1
+			}).then(files => {
+				if (files.length == this.limit + 1) {
+					files.pop();
+					this.existMore = true;
+				} else {
+					this.existMore = false;
+				}
+				this.files = this.files.concat(files);
+				this.offset += this.limit;
+			});
+		},
+
+		thumbnail(file: any): any {
+			return {
+				'background-color': file.properties.avgColor && file.properties.avgColor.length == 3 ? `rgb(${file.properties.avgColor.join(',')})` : 'transparent',
+				'background-image': `url(${file.thumbnailUrl})`
+			};
+		}
+	}
+});
+</script>
+
+<style lang="stylus" scoped>
+.pwnqwyet
+	@media (min-width 500px)
+		padding 16px
+
+	.kidvdlkg
+		display flex
+		padding 16px 0
+		border-top solid 1px var(--faceDivider)
+
+		> div:first-child
+			> .thumbnail
+				display block
+				width 64px
+				height 64px
+				background-size cover
+				background-position center center
+
+		> div:last-child
+			flex 1
+			padding-left 16px
+
+			> header
+				> .username
+					margin-left 8px
+					opacity 0.7
+
+</style>
diff --git a/src/client/app/admin/views/index.vue b/src/client/app/admin/views/index.vue
index 3da13ad214..9524a98542 100644
--- a/src/client/app/admin/views/index.vue
+++ b/src/client/app/admin/views/index.vue
@@ -22,12 +22,11 @@
 			<li @click="nav('instance')" :class="{ active: page == 'instance' }"><fa icon="cog" fixed-width/>{{ $t('instance') }}</li>
 			<li @click="nav('moderators')" :class="{ active: page == 'moderators' }"><fa :icon="faHeadset" fixed-width/>{{ $t('moderators') }}</li>
 			<li @click="nav('users')" :class="{ active: page == 'users' }"><fa icon="users" fixed-width/>{{ $t('users') }}</li>
+			<li @click="nav('drive')" :class="{ active: page == 'drive' }"><fa icon="cloud" fixed-width/>{{ $t('@.drive') }}</li>
 			<!-- <li @click="nav('federation')" :class="{ active: page == 'federation' }"><fa :icon="faShareAlt" fixed-width/>{{ $t('federation') }}</li> -->
 			<li @click="nav('emoji')" :class="{ active: page == 'emoji' }"><fa :icon="faGrin" fixed-width/>{{ $t('emoji') }}</li>
 			<li @click="nav('announcements')" :class="{ active: page == 'announcements' }"><fa icon="broadcast-tower" fixed-width/>{{ $t('announcements') }}</li>
 			<li @click="nav('hashtags')" :class="{ active: page == 'hashtags' }"><fa icon="hashtag" fixed-width/>{{ $t('hashtags') }}</li>
-
-			<!-- <li @click="nav('drive')" :class="{ active: page == 'drive' }"><fa icon="cloud" fixed-width/>{{ $t('@.drive') }}</li> -->
 		</ul>
 		<div class="back-to-misskey">
 			<a href="/"><fa :icon="faArrowLeft"/> {{ $t('back-to-misskey') }}</a>
@@ -45,7 +44,7 @@
 			<div v-if="page == 'emoji'"><x-emoji/></div>
 			<div v-if="page == 'announcements'"><x-announcements/></div>
 			<div v-if="page == 'hashtags'"><x-hashtags/></div>
-			<div v-if="page == 'drive'"></div>
+			<div v-if="page == 'drive'"><x-drive/></div>
 			<div v-if="page == 'update'"></div>
 		</div>
 	</main>
@@ -63,6 +62,7 @@ import XEmoji from "./emoji.vue";
 import XAnnouncements from "./announcements.vue";
 import XHashtags from "./hashtags.vue";
 import XUsers from "./users.vue";
+import XDrive from "./drive.vue";
 import { faHeadset, faArrowLeft, faShareAlt } from '@fortawesome/free-solid-svg-icons';
 import { faGrin } from '@fortawesome/free-regular-svg-icons';
 
@@ -79,7 +79,8 @@ export default Vue.extend({
 		XEmoji,
 		XAnnouncements,
 		XHashtags,
-		XUsers
+		XUsers,
+		XDrive,
 	},
 	provide: {
 		isMobile
diff --git a/src/models/drive-file.ts b/src/models/drive-file.ts
index e4c1598049..24c7ac75c0 100644
--- a/src/models/drive-file.ts
+++ b/src/models/drive-file.ts
@@ -1,6 +1,7 @@
 import * as mongo from 'mongodb';
 const deepcopy = require('deepcopy');
 import { pack as packFolder } from './drive-folder';
+import { pack as packUser } from './user';
 import monkDb, { nativeDbConn } from '../db/mongodb';
 import isObjectId from '../misc/is-objectid';
 import getDriveFileUrl, { getOriginalUrl } from '../misc/get-drive-file-url';
@@ -131,6 +132,7 @@ export const packMany = (
 	options?: {
 		detail?: boolean
 		self?: boolean,
+		withUser?: boolean,
 	}
 ) => {
 	return Promise.all(files.map(f => pack(f, options)));
@@ -144,6 +146,7 @@ export const pack = (
 	options?: {
 		detail?: boolean,
 		self?: boolean,
+		withUser?: boolean,
 	}
 ) => new Promise<any>(async (resolve, reject) => {
 	const opts = Object.assign({
@@ -208,6 +211,11 @@ export const pack = (
 		*/
 	}
 
+	if (opts.withUser) {
+		// Populate user
+		_target.user = await packUser(_file.metadata.userId);
+	}
+
 	delete _target.withoutChunks;
 	delete _target.storage;
 	delete _target.storageProps;
diff --git a/src/server/api/endpoints/admin/drive/files.ts b/src/server/api/endpoints/admin/drive/files.ts
new file mode 100644
index 0000000000..2e54270a0f
--- /dev/null
+++ b/src/server/api/endpoints/admin/drive/files.ts
@@ -0,0 +1,79 @@
+import $ from 'cafy';
+import File, { packMany } from '../../../../../models/drive-file';
+import define from '../../../define';
+
+export const meta = {
+	requireCredential: false,
+	requireModerator: true,
+
+	params: {
+		limit: {
+			validator: $.num.optional.range(1, 100),
+			default: 10
+		},
+
+		offset: {
+			validator: $.num.optional.min(0),
+			default: 0
+		},
+
+		sort: {
+			validator: $.str.optional.or([
+				'+createdAt',
+				'-createdAt',
+				'+size',
+				'-size',
+			]),
+		},
+
+		origin: {
+			validator: $.str.optional.or([
+				'combined',
+				'local',
+				'remote',
+			]),
+			default: 'local'
+		}
+	}
+};
+
+export default define(meta, (ps, me) => new Promise(async (res, rej) => {
+	let _sort;
+	if (ps.sort) {
+		if (ps.sort == '+createdAt') {
+			_sort = {
+				uploadDate: -1
+			};
+		} else if (ps.sort == '-createdAt') {
+			_sort = {
+				uploadDate: 1
+			};
+		} else if (ps.sort == '+size') {
+			_sort = {
+				length: -1
+			};
+		} else if (ps.sort == '+size') {
+			_sort = {
+				length: -1
+			};
+		}
+	} else {
+		_sort = {
+			_id: -1
+		};
+	}
+
+	const q =
+		ps.origin == 'local' ? { host: null } :
+		ps.origin == 'remote' ? { host: { $ne: null } } :
+		{};
+
+	const files = await File
+		.find(q, {
+			limit: ps.limit,
+			sort: _sort,
+			skip: ps.offset
+		});
+
+	res(await packMany(files, { detail: true, withUser: true }));
+}));