diff --git a/opentech/apply/stream_forms/blocks.py b/opentech/apply/stream_forms/blocks.py
index fd7dcdfaf08550809dc5a5451691061ac584fcba..9e3bd04f85e6127ed399c6e1bf58ab6b35a73087 100644
--- a/opentech/apply/stream_forms/blocks.py
+++ b/opentech/apply/stream_forms/blocks.py
@@ -3,7 +3,10 @@ import bleach
 from django_bleach.templatetags.bleach_tags import bleach_value
 
 from django import forms
+from django.conf import settings
+from django.core.validators import FileExtensionValidator
 from django.db.models import BLANK_CHOICE_DASH
+from django.forms.widgets import ClearableFileInput
 from django.utils.dateparse import parse_datetime
 from django.utils.encoding import force_text
 from django.utils.text import slugify
@@ -327,11 +330,20 @@ class FileFieldBlock(UploadableMediaBlock):
     You must implement this if you want to reuse it.
     """
     field_class = forms.FileField
+    widget = ClearableFileInput
 
     class Meta:
         label = _('File field')
         icon = 'download'
 
+    def get_field_kwargs(self, struct_value):
+        kwargs = super().get_field_kwargs(struct_value)
+        kwargs['validators'] = [
+            FileExtensionValidator(allowed_extensions=settings.FILE_ALLOWED_EXTENSIONS)
+        ]
+        kwargs['widget'] = self.get_widget(struct_value)(attrs={'accept': settings.FILE_ACCEPT_ATTR_VALUE})
+        return kwargs
+
 
 class MultiFileFieldBlock(UploadableMediaBlock):
     field_class = MultiFileField
diff --git a/opentech/apply/stream_forms/fields.py b/opentech/apply/stream_forms/fields.py
index c45d4f1337f7f482c984b52976827e52c3e92baa..c7a8deed5921ec957558420f721f73f737fdcbef 100644
--- a/opentech/apply/stream_forms/fields.py
+++ b/opentech/apply/stream_forms/fields.py
@@ -1,3 +1,5 @@
+from django.conf import settings
+from django.core.validators import FileExtensionValidator
 from django.forms import ClearableFileInput, FileField, CheckboxInput
 
 
@@ -63,7 +65,11 @@ class MultiFileField(FileField):
         cleared = value['cleared']
         if not files and not cleared:
             return initial
-        new = [FileField().clean(file, initial) for file in files]
+        new = [
+            FileField(validators=[
+                FileExtensionValidator(allowed_extensions=settings.FILE_ALLOWED_EXTENSIONS)
+            ]).clean(file, initial) for file in files
+        ]
 
         if initial:
             old = [file for i, file in enumerate(initial) if i not in cleared]
@@ -71,3 +77,9 @@ class MultiFileField(FileField):
             old = []
 
         return old + new
+
+    def widget_attrs(self, widget):
+        attrs = super().widget_attrs(widget)
+        if isinstance(widget, MultiFileInput) and 'accept' not in widget.attrs:
+            attrs.setdefault('accept', settings.FILE_ACCEPT_ATTR_VALUE)
+        return attrs
diff --git a/opentech/settings/base.py b/opentech/settings/base.py
index ca17c3ff66873d59355387e1ff0c228ca0b8195e..c3e26f3254393ae8c7160694c60cc355cf78e804 100644
--- a/opentech/settings/base.py
+++ b/opentech/settings/base.py
@@ -438,6 +438,12 @@ BLEACH_STRIP_TAGS = True
 
 BLEACH_STRIP_COMMENTS = True
 
+# File Field settings
+FILE_ALLOWED_EXTENSIONS = ['doc', 'docx', 'odp', 'ods', 'odt', 'pdf', 'ppt', 'pptx', 'rtf', 'txt', 'xls', 'xlsx']
+
+# Accept attribute in input tag of type file needs filename extensions, starting with a period (".") character.
+FILE_ACCEPT_ATTR_VALUE = ", ".join(['.' + ext for ext in FILE_ALLOWED_EXTENSIONS])
+
 # Hijack Settings
 HIJACK_LOGIN_REDIRECT_URL = '/dashboard/'
 HIJACK_LOGOUT_REDIRECT_URL = '/account/'