diff --git a/doc/changes.rst b/doc/changes.rst
index 2cf0875..68483d1 100644
--- a/doc/changes.rst
+++ b/doc/changes.rst
@@ -8,6 +8,8 @@ Changes
 
 *   String types handling is clearer.
 
+*   New FileType type.
+
 *   Supports cross-referenced types.
 
 *   Various bugfixes.
diff --git a/doc/types.rst b/doc/types.rst
index f1ef3db..5c8ecec 100644
--- a/doc/types.rst
+++ b/doc/types.rst
@@ -50,6 +50,11 @@ The native types are :
     
             A time (:py:class:`datetime.time`)
 
+    -   .. wsme:type:: Filetype
+
+            A file (:py:class:`wsme.types.Filetype`). Currently FileType is
+            supported only as input type on protocols that accept form inputs.
+
     -   Arrays -- This is a special case. When stating a list
         datatype, always state its content type as the unique element
         of a list. Example::
diff --git a/examples/demo/demo.cfg b/examples/demo/demo.cfg
deleted file mode 100644
index 4fdca0d..0000000
--- a/examples/demo/demo.cfg
+++ /dev/null
@@ -1,7 +0,0 @@
-[app:main]
-paste.app_factory = demo:app_factory
-
-[server:main]
-use = egg:PasteScript#wsgiutils
-host = 127.0.0.1
-port = 8989
diff --git a/examples/demo/demo.py b/examples/demo/demo.py
index 24ef8ab..dd488fa 100644
--- a/examples/demo/demo.py
+++ b/examples/demo/demo.py
@@ -8,11 +8,13 @@ To run it::
 
 Then::
 
-    paster serve demo.cfg
+    python demo.py
 """
 
 from wsme import WSRoot, expose, validate
-from wsme.wsgi import adapt
+from wsme.types import FileType
+
+import bottle
 
 from six import u
 
@@ -31,6 +33,11 @@ class DemoRoot(WSRoot):
     def multiply(self, a, b):
         return a * b
 
+    @expose(unicode)
+    @validate(FileType)
+    def echofile(self, afile):
+        return unicode(afile.value)
+
     @expose(unicode)
     def helloworld(self):
         return u"こんにちは世界 (<- Hello World in Japanese !)"
@@ -68,17 +75,17 @@ class DemoRoot(WSRoot):
         return persons
 
 
-def app_factory(global_config, **local_conf):
-    root = DemoRoot()
+root = DemoRoot(webpath='/ws')
 
-    root.addprotocol('soap',
-            tns='http://example.com/demo',
-            typenamespace='http://example.com/demo/types',
-            baseURL='http://127.0.0.1:8989/',
-    )
+root.addprotocol('soap',
+        tns='http://example.com/demo',
+        typenamespace='http://example.com/demo/types',
+        baseURL='http://127.0.0.1:8989/ws/',
+)
 
-    root.addprotocol('restjson')
+root.addprotocol('restjson')
 
-    return adapt(root)
+bottle.mount('/ws/', root.wsgiapp())
 
 logging.basicConfig(level=logging.DEBUG)
+bottle.run()
diff --git a/examples/demo/setup.py b/examples/demo/setup.py
index 4ca4a76..b623851 100644
--- a/examples/demo/setup.py
+++ b/examples/demo/setup.py
@@ -4,9 +4,7 @@ setup(name='demo',
     install_requires=[
         'WSME',
         'WSME-Soap',
-        'PasteScript',
-        'PasteDeploy',
-        'WSGIUtils',
+        'Bottle',
         'Pygments',
     ],
     package=['demo'])
diff --git a/wsme/protocols/commons.py b/wsme/protocols/commons.py
index 2ed4d7c..d7d912d 100644
--- a/wsme/protocols/commons.py
+++ b/wsme/protocols/commons.py
@@ -1,10 +1,11 @@
+import cgi
 import datetime
 import re
 
 from simplegeneric import generic
 
 from wsme.types import iscomplex, list_attributes, Unset
-from wsme.types import UserType, ArrayType, DictType
+from wsme.types import UserType, ArrayType, DictType, FileType
 from wsme.utils import parse_isodate, parse_isotime, parse_isodatetime
 
 
@@ -31,6 +32,13 @@ def datetime_from_param(datatype, value):
     return parse_isodatetime(value) if value else None
 
 
+@from_param.when_object(FileType)
+def filetype_from_param(datatype, value):
+    if isinstance(value, cgi.FieldStorage):
+        return FileType(fieldstorage=value)
+    return FileType(content=value)
+
+
 @from_param.when_type(UserType)
 def usertype_from_param(datatype, value):
     return datatype.frombasetype(
diff --git a/wsme/types.py b/wsme/types.py
index b04d91e..81be364 100644
--- a/wsme/types.py
+++ b/wsme/types.py
@@ -140,6 +140,32 @@ class Enum(UserType):
         return value
 
 
+class FileType(object):
+    def __init__(self, filename=None, file=None, content=None,
+            contenttype=None, fieldstorage=None):
+        self.filename = filename
+        self._file = file
+        self._content = content
+        self.contenttype = contenttype
+        if fieldstorage is not None:
+            if fieldstorage.file:
+                self._file = fieldstorage.file
+                self.filename = fieldstorage.filename
+                self.contenttype = fieldstorage.type
+            else:
+                self._content = fieldstorage.value
+
+    @property
+    def file(self):
+        return self._file
+
+    @property
+    def value(self):
+        if self._content is None and self._file:
+            self._content = self._file.read()
+        return self._content
+
+
 class UnsetType(object):
     if sys.version < '3':
         def __nonzero__(self):
@@ -154,7 +180,7 @@ Unset = UnsetType()
 pod_types = six.integer_types + (
     bytes, text, float, bool)
 dt_types = (datetime.date, datetime.time, datetime.datetime)
-extra_types = (binary, decimal.Decimal)
+extra_types = (binary, decimal.Decimal, FileType)
 native_types = pod_types + dt_types + extra_types