diff --git a/src/client/app/common/views/components/media-list.vue b/src/client/app/common/views/components/media-list.vue
index 6c54967eb7..bfbc9366d3 100644
--- a/src/client/app/common/views/components/media-list.vue
+++ b/src/client/app/common/views/components/media-list.vue
@@ -42,7 +42,7 @@ export default Vue.extend({
 	},
 	methods: {
 		previewable(file) {
-			return file.type.startsWith('video') || file.type.startsWith('image');
+			return (file.type.startsWith('video') || file.type.startsWith('image')) && file.thumbnailUrl;
 		}
 	}
 });
diff --git a/src/server/file/send-drive-file.ts b/src/server/file/send-drive-file.ts
index 1a43e5dc42..2283435794 100644
--- a/src/server/file/send-drive-file.ts
+++ b/src/server/file/send-drive-file.ts
@@ -9,7 +9,7 @@ import { DriveFiles } from '../../models';
 import { InternalStorage } from '../../services/drive/internal-storage';
 import { downloadUrl } from '../../misc/donwload-url';
 import { detectMine } from '../../misc/detect-mine';
-import { convertToJpeg, convertToPng, convertToGif, convertToApng } from '../../services/drive/image-processor';
+import { convertToJpeg, convertToPng } from '../../services/drive/image-processor';
 import { GenerateVideoThumbnail } from '../../services/drive/generate-video-thumbnail';
 
 const assets = `${__dirname}/../../server/file/assets/`;
@@ -60,10 +60,6 @@ export default async function(ctx: Koa.Context) {
 							return await convertToJpeg(path, 498, 280);
 						} else if (['image/png'].includes(type)) {
 							return await convertToPng(path, 498, 280);
-						} else if (['image/gif'].includes(type)) {
-							return await convertToGif(path);
-						} else if (['image/apng', 'image/vnd.mozilla.apng'].includes(type)) {
-							return await convertToApng(path);
 						} else if (type.startsWith('video/')) {
 							return await GenerateVideoThumbnail(path);
 						}
@@ -101,22 +97,23 @@ export default async function(ctx: Koa.Context) {
 		return;
 	}
 
-	if (isThumbnail) {
+	if (isThumbnail || isWebpublic) {
+		const [mime, ext] = await detectMine(InternalStorage.resolvePath(key));
+		const filename = rename(file.name, {
+			suffix: isThumbnail ? '-thumb' : '-web',
+			extname: ext ? `.${ext}` : undefined
+		}).toString();
+
 		ctx.body = InternalStorage.read(key);
-		ctx.set('Content-Type', 'image/jpeg');
+		ctx.set('Content-Type', mime);
 		ctx.set('Cache-Control', 'max-age=31536000, immutable');
-		ctx.set('Content-Disposition', contentDisposition('inline', `${rename(file.name, { suffix: '-thumb', extname: '.jpeg' })}`));
-	} else if (isWebpublic) {
-		ctx.body = InternalStorage.read(key);
-		ctx.set('Content-Type', file.type === 'image/apng' ? 'image/png' : file.type);
-		ctx.set('Cache-Control', 'max-age=31536000, immutable');
-		ctx.set('Content-Disposition', contentDisposition('inline', `${rename(file.name, { suffix: '-web' })}`));
+		ctx.set('Content-Disposition', contentDisposition('inline', filename));
 	} else {
 		const readable = InternalStorage.read(file.accessKey!);
 		readable.on('error', commonReadableHandlerGenerator(ctx));
 		ctx.body = readable;
 		ctx.set('Content-Type', file.type);
 		ctx.set('Cache-Control', 'max-age=31536000, immutable');
-		ctx.set('Content-Disposition', contentDisposition('inline', `${file.name}`));
+		ctx.set('Content-Disposition', contentDisposition('inline', file.name));
 	}
 }
diff --git a/src/services/drive/add-file.ts b/src/services/drive/add-file.ts
index 54aa018a46..350e4dfe19 100644
--- a/src/services/drive/add-file.ts
+++ b/src/services/drive/add-file.ts
@@ -159,6 +159,8 @@ export async function generateAlts(path: string, type: string, generateWeb: bool
 				webpublic = await convertToWebp(path, 2048, 2048);
 			} else if (['image/png'].includes(type)) {
 				webpublic = await convertToPng(path, 2048, 2048);
+			} else {
+				logger.debug(`web image not created (not an required image)`);
 			}
 		} catch (e) {
 			logger.warn(`web image not created (an error occured)`, e);
@@ -180,8 +182,10 @@ export async function generateAlts(path: string, type: string, generateWeb: bool
 			try {
 				thumbnail = await GenerateVideoThumbnail(path);
 			} catch (e) {
-				logger.error(`GenerateVideoThumbnail failed: ${e}`);
+				logger.warn(`GenerateVideoThumbnail failed: ${e}`);
 			}
+		} else {
+			logger.debug(`thumbnail not created (not an required file)`);
 		}
 	} catch (e) {
 		logger.warn(`thumbnail not created (an error occured)`, e);
@@ -351,7 +355,7 @@ export default async function(
 
 	let propPromises: Promise<void>[] = [];
 
-	const isImage = ['image/jpeg', 'image/gif', 'image/png', 'image/apng', 'image/vnd.mozilla.apng', 'image/webp'].includes(mime);
+	const isImage = ['image/jpeg', 'image/gif', 'image/png', 'image/apng', 'image/vnd.mozilla.apng', 'image/webp', 'image/svg+xml'].includes(mime);
 
 	if (isImage) {
 		const img = sharp(path);
@@ -374,15 +378,21 @@ export default async function(
 			logger.debug('calculating average color...');
 
 			try {
-				const info = await (img as any).stats();
+				const info = await img.stats();
 
-				const r = Math.round(info.channels[0].mean);
-				const g = Math.round(info.channels[1].mean);
-				const b = Math.round(info.channels[2].mean);
+				if (info.isOpaque) {
+					const r = Math.round(info.channels[0].mean);
+					const g = Math.round(info.channels[1].mean);
+					const b = Math.round(info.channels[2].mean);
 
-				logger.debug(`average color is calculated: ${r}, ${g}, ${b}`);
+					logger.debug(`average color is calculated: ${r}, ${g}, ${b}`);
 
-				properties['avgColor'] = `rgb(${r},${g},${b})`;
+					properties['avgColor'] = `rgb(${r},${g},${b})`;
+				} else {
+					logger.debug(`this image is not opaque so average color is 255, 255, 255`);
+
+					properties['avgColor'] = `rgb(255,255,255)`;
+				}
 			} catch (e) { }
 		};
 
diff --git a/src/services/drive/image-processor.ts b/src/services/drive/image-processor.ts
index e2dd90cfa0..21a05fa9e4 100644
--- a/src/services/drive/image-processor.ts
+++ b/src/services/drive/image-processor.ts
@@ -1,5 +1,4 @@
 import * as sharp from 'sharp';
-import * as fs from 'fs';
 
 export type IImage = {
 	data: Buffer;
diff --git a/src/services/drive/internal-storage.ts b/src/services/drive/internal-storage.ts
index ff890d7d47..f8d7489a22 100644
--- a/src/services/drive/internal-storage.ts
+++ b/src/services/drive/internal-storage.ts
@@ -3,25 +3,27 @@ import * as Path from 'path';
 import config from '../../config';
 
 export class InternalStorage {
-	private static readonly path = Path.resolve(`${__dirname}/../../../files`);
+	private static readonly path = Path.resolve(__dirname, '../../../files');
+
+	public static resolvePath = (key: string) => Path.resolve(InternalStorage.path, key);
 
 	public static read(key: string) {
-		return fs.createReadStream(`${InternalStorage.path}/${key}`);
+		return fs.createReadStream(InternalStorage.resolvePath(key));
 	}
 
 	public static saveFromPath(key: string, srcPath: string) {
 		fs.mkdirSync(InternalStorage.path, { recursive: true });
-		fs.copyFileSync(srcPath, `${InternalStorage.path}/${key}`);
+		fs.copyFileSync(srcPath, InternalStorage.resolvePath(key));
 		return `${config.url}/files/${key}`;
 	}
 
 	public static saveFromBuffer(key: string, data: Buffer) {
 		fs.mkdirSync(InternalStorage.path, { recursive: true });
-		fs.writeFileSync(`${InternalStorage.path}/${key}`, data);
+		fs.writeFileSync(InternalStorage.resolvePath(key), data);
 		return `${config.url}/files/${key}`;
 	}
 
 	public static del(key: string) {
-		fs.unlink(`${InternalStorage.path}/${key}`, () => {});
+		fs.unlink(InternalStorage.resolvePath(key), () => {});
 	}
 }