diff --git a/scripts/langindex.json b/scripts/langindex.json
index df9739345..a3738eb16 100644
--- a/scripts/langindex.json
+++ b/scripts/langindex.json
@@ -1373,6 +1373,7 @@
   "core.cannotconnecttrouble": "local_moodlemobileapp",
   "core.cannotconnectverify": "local_moodlemobileapp",
   "core.cannotdownloadfiles": "local_moodlemobileapp",
+  "core.cannotopeninapp": "moodle",
   "core.captureaudio": "local_moodlemobileapp",
   "core.capturedimage": "local_moodlemobileapp",
   "core.captureimage": "local_moodlemobileapp",
@@ -1916,6 +1917,7 @@
   "core.offline": "message",
   "core.ok": "moodle",
   "core.online": "message",
+  "core.openfile": "moodle",
   "core.openfullimage": "local_moodlemobileapp",
   "core.openinbrowser": "local_moodlemobileapp",
   "core.openmodinbrowser": "local_moodlemobileapp",
diff --git a/src/addon/mod/resource/providers/helper.ts b/src/addon/mod/resource/providers/helper.ts
index 62a00e511..8f43d77ee 100644
--- a/src/addon/mod/resource/providers/helper.ts
+++ b/src/addon/mod/resource/providers/helper.ts
@@ -183,7 +183,19 @@ export class AddonModResourceHelperProvider {
      * @param courseId Course Id, used for completion purposes.
      * @return Resolved when done.
      */
-    openModuleFile(module: any, courseId: number): Promise<any> {
+    async openModuleFile(module: any, courseId: number): Promise<any> {
+        // Check whether the file type excluded to open in app.
+        if (!module.contents.length) {
+            await this.courseProvider.loadModuleContents(module, courseId);
+        }
+
+        if (!this.fileHelper.isOpenableInApp(module.contents[0])) {
+            const confirmed = await this.fileHelper.showConfirmOpenUnsupportedFile();
+            if (!confirmed) {
+                return;
+            }
+        }
+
         const modal = this.domUtils.showModalLoading();
 
         // Download and open the file from the resource contents.
diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json
index 6d3fd2ffe..699eea430 100644
--- a/src/assets/lang/en.json
+++ b/src/assets/lang/en.json
@@ -1373,6 +1373,7 @@
     "core.cannotconnecttrouble": "We're having trouble connecting to your site.",
     "core.cannotconnectverify": "<strong>Please check the address is correct.</strong>",
     "core.cannotdownloadfiles": "File downloading is disabled. Please contact your site administrator.",
+    "core.cannotopeninapp": "This file may not work as expected on this device. Would you like to open it anyway?",
     "core.captureaudio": "Record audio",
     "core.capturedimage": "Taken picture.",
     "core.captureimage": "Take picture",
@@ -1916,6 +1917,7 @@
     "core.offline": "Offline",
     "core.ok": "OK",
     "core.online": "Online",
+    "core.openfile": "Open file",
     "core.openfullimage": "Click here to display the full size image",
     "core.openinbrowser": "Open in browser",
     "core.openmodinbrowser": "Open {{$a}} in browser",
diff --git a/src/components/file/file.ts b/src/components/file/file.ts
index 5df003e25..d920b54f9 100644
--- a/src/components/file/file.ts
+++ b/src/components/file/file.ts
@@ -148,7 +148,7 @@ export class CoreFileComponent implements OnInit, OnDestroy {
      * @param e Click event.
      * @param openAfterDownload Whether the file should be opened after download.
      */
-    download(e?: Event, openAfterDownload: boolean = false): void {
+    async download(e?: Event, openAfterDownload: boolean = false): Promise<void> {
         e && e.preventDefault();
         e && e.stopPropagation();
 
@@ -156,6 +156,13 @@ export class CoreFileComponent implements OnInit, OnDestroy {
             return;
         }
 
+        if (!this.fileHelper.isOpenableInApp(this.file)) {
+            const confirmed = await this.fileHelper.showConfirmOpenUnsupportedFile();
+            if (!confirmed) {
+                return;
+            }
+        }
+
         if (!this.canDownload || !this.state || this.state == CoreConstants.NOT_DOWNLOADABLE) {
             // File cannot be downloaded, just open it.
             if (this.file.toURL) {
diff --git a/src/lang/en.json b/src/lang/en.json
index 40da0174b..97fcaba84 100644
--- a/src/lang/en.json
+++ b/src/lang/en.json
@@ -16,6 +16,7 @@
     "cannotconnecttrouble": "We're having trouble connecting to your site.",
     "cannotconnectverify": "<strong>Please check the address is correct.</strong>",
     "cannotdownloadfiles": "File downloading is disabled. Please contact your site administrator.",
+    "cannotopeninapp": "This file may not work as expected on this device. Would you like to open it anyway?",
     "captureaudio": "Record audio",
     "capturedimage": "Taken picture.",
     "captureimage": "Take picture",
@@ -200,6 +201,7 @@
     "offline": "Offline",
     "ok": "OK",
     "online": "Online",
+    "openfile": "Open file",
     "openfullimage": "Click here to display the full size image",
     "openinbrowser": "Open in browser",
     "openmodinbrowser": "Open {{$a}} in browser",
diff --git a/src/providers/file-helper.ts b/src/providers/file-helper.ts
index 9a9ab8eaf..11e0e6345 100644
--- a/src/providers/file-helper.ts
+++ b/src/providers/file-helper.ts
@@ -15,6 +15,7 @@
 import { Injectable } from '@angular/core';
 import { TranslateService } from '@ngx-translate/core';
 import { CoreAppProvider } from './app';
+import { CoreDomUtilsProvider } from '@providers/utils/dom';
 import { CoreFileProvider } from './file';
 import { CoreFilepoolProvider } from './filepool';
 import { CoreSitesProvider } from './sites';
@@ -30,7 +31,8 @@ import { makeSingleton } from '@singletons/core.singletons';
 @Injectable()
 export class CoreFileHelperProvider {
 
-    constructor(protected fileProvider: CoreFileProvider,
+    constructor(protected domUtils: CoreDomUtilsProvider,
+            protected fileProvider: CoreFileProvider,
             protected filepoolProvider: CoreFilepoolProvider,
             protected sitesProvider: CoreSitesProvider,
             protected appProvider: CoreAppProvider,
@@ -339,6 +341,57 @@ export class CoreFileHelperProvider {
 
         throw new Error('Couldn\'t determine file size: ' + file.fileurl);
     }
+
+    /**
+     * Is the file openable in app.
+     *
+     * @param file The file to check.
+     * @return bool.
+     */
+    isOpenableInApp(file: any): boolean {
+        const re = /(?:\.([^.]+))?$/;
+
+        const ext = re.exec(file.filename)[1];
+
+        return !this.isFileTypeExcludedInApp(ext);
+    }
+
+    /**
+     * Is the file openable in app.
+     *
+     * @param file The file to check.
+     * @return bool.
+     */
+    async showConfirmOpenUnsupportedFile(): Promise<boolean> {
+        try {
+            await this.domUtils.showConfirm(this.translate.instant('core.cannotopeninapp'), undefined,
+                this.translate.instant('core.openfile'));
+
+            return true;
+        }
+        catch (e) {
+            return false;
+        }
+    }
+
+    /**
+     * Is the file type excluded to open in app.
+     *
+     * @param file The file to check.
+     * @return bool.
+     */
+    isFileTypeExcludedInApp(fileType: string): boolean {
+        const currentSite = this.sitesProvider.getCurrentSite();
+        const fileTypeExcludeList = currentSite && currentSite.getStoredConfig('tool_mobile_filetypeexclusionlist');
+
+        if (!fileTypeExcludeList) {
+            return false;
+        }
+
+        const regEx = new RegExp('(,|^)' + fileType + '(,|$)', 'g');
+
+        return !!fileTypeExcludeList.match(regEx);
+    }
 }
 
 export class CoreFileHelper extends makeSingleton(CoreFileHelperProvider) {}