diff --git a/src/leap/soledad/server/_blobs.py b/src/leap/soledad/server/_blobs.py
index bfe95516abc1192dfb069d055f658103c4b08866..4a963e1054d041151818a04395ab2b22798b3ef0 100644
--- a/src/leap/soledad/server/_blobs.py
+++ b/src/leap/soledad/server/_blobs.py
@@ -29,6 +29,8 @@ import base64
 import json
 import re
 
+from twisted.python.compat import intToBytes
+from twisted.web import http
 from twisted.web import static
 from twisted.web import resource
 from twisted.web.client import FileBodyProducer
@@ -95,8 +97,8 @@ class FilesystemBlobsBackend(object):
         logger.info('reading blob: %s - %s@%s' % (user, blob_id, namespace))
         path = self._get_path(user, blob_id, namespace)
         logger.debug('blob path: %s' % path)
-        res = static.File(path, defaultType='application/octet-stream')
-        return res
+        fd = open(path)
+        return defer.succeed(fd)
 
     def get_flags(self, user, blob_id, namespace=''):
         path = self._get_path(user, blob_id, namespace)
@@ -257,6 +259,23 @@ class ImproperlyConfiguredException(Exception):
     pass
 
 
+class BlobFile(resource.Resource):
+
+    def __init__(self, fd):
+        self.fd = fd
+        self.fd.seek(0, 2)
+        self.size = self.fd.tell()
+        self.fd.seek(0)
+
+    def render_GET(self, request):
+        request.setHeader(b'content-length', intToBytes(self.size))
+        request.setHeader(b'content-type', 'application/octet-stream')
+        request.setResponseCode(http.OK)
+        producer = static.NoRangeStaticProducer(request, self.fd)
+        producer.start()
+        return NOT_DONE_YET
+
+
 class BlobsResource(resource.Resource):
 
     isLeaf = True
@@ -296,22 +315,32 @@ class BlobsResource(resource.Resource):
             d.addCallback(lambda blobs: request.write(blobs))
             d.addCallback(lambda _: request.finish())
             return NOT_DONE_YET
-        only_flags = request.args.get('only_flags', [False])[0]
-        try:
-            if only_flags:
-                d = self._handler.get_flags(user, blob_id, namespace)
-                d.addCallback(lambda flags: json.dumps(flags))
-                d.addCallback(lambda flags: request.write(flags))
-                d.addCallback(lambda _: request.finish())
-                return NOT_DONE_YET
-            tag = self._handler.get_tag(user, blob_id, namespace)
-            request.responseHeaders.setRawHeaders('Tag', [tag])
-        except BlobNotFound:
-            # 404 - Not Found
+
+        def catchBlobNotFound(failure):
+            failure.trap(BlobNotFound)
             request.setResponseCode(404)
-            return "Blob doesn't exists: %s" % blob_id
-        res = self._handler.read_blob(user, blob_id, namespace=namespace)
-        return res.render_GET(request)
+            request.write("Blob doesn't exists: %s" % blob_id)
+            request.finish()
+
+        only_flags = request.args.get('only_flags', [False])[0]
+        if only_flags:
+            d = self._handler.get_flags(user, blob_id, namespace)
+            d.addErrback(catchBlobNotFound)
+            d.addCallback(lambda flags: json.dumps(flags))
+            d.addCallback(lambda flags: request.write(flags))
+            d.addCallback(lambda _: request.finish())
+            return NOT_DONE_YET
+
+        d = self._handler.get_tag(user, blob_id, namespace)
+        d.addCallback(
+            lambda tag: request.responseHeaders.setRawHeaders(
+                'Tag', [tag]))
+        d.addCallback(lambda _: self._handler.read_blob(user, blob_id,
+                                                        namespace=namespace))
+        d.addCallback(lambda fd: BlobFile(fd))
+        d.addCallback(lambda res: res.render_GET(request))
+
+        return NOT_DONE_YET
 
     def render_DELETE(self, request):
         logger.info("http put: %s" % request.path)
diff --git a/src/leap/soledad/server/interfaces.py b/src/leap/soledad/server/interfaces.py
index 358a0d62c0631e3eeee4ac07f1a7e045c1ea20c0..d7a4aa70941f464c4994919e2e0c9cbf19f50b71 100644
--- a/src/leap/soledad/server/interfaces.py
+++ b/src/leap/soledad/server/interfaces.py
@@ -27,7 +27,7 @@ class IBlobsBackend(Interface):
 
     def read_blob(user, blob_id, namespace=''):
         """
-        Read a blob from the backend storage return it as a twisted resource.
+        Read a blob from the backend storage.
 
         :param user: The id of the user who owns the blob.
         :type user: str
@@ -36,8 +36,9 @@ class IBlobsBackend(Interface):
         :param namespace: An optional namespace for the blob.
         :type namespace: str
 
-        :return: The blob as a twisted resource.
-        :rtype: twisted.web.resource.Resource
+        :return: A deferred that fires with a file-like object that gives
+            access to the contents of the blob.
+        :rtype: twisted.internet.defer.Deferred
         """
 
     def write_blob(user, blob_id, fd, namespace=''):
diff --git a/tests/blobs/test_fs_backend.py b/tests/blobs/test_fs_backend.py
index e7ace66ed5ab5e9a04ea64fce6a19e28f532be77..5da0661c6d15cfbdc1acfa73f1065ccad8dc7a93 100644
--- a/tests/blobs/test_fs_backend.py
+++ b/tests/blobs/test_fs_backend.py
@@ -61,21 +61,15 @@ class FilesystemBackendTestCase(unittest.TestCase):
         self.assertEquals(10, size)
 
     @pytest.mark.usefixtures("method_tmpdir")
-    @mock.patch.object(_blobs.static, 'File')
+    @mock.patch('leap.soledad.server._blobs.open')
     @mock.patch.object(_blobs.FilesystemBlobsBackend, '_get_path',
                        Mock(return_value='path'))
-    def test_read_blob(self, file_mock):
-        render_mock = Mock()
-        file_mock.return_value = render_mock
+    @defer.inlineCallbacks
+    def test_read_blob(self, open):
         backend = _blobs.FilesystemBlobsBackend(blobs_path=self.tempdir)
-        request = DummyRequest([''])
-        resource = backend.read_blob('user', 'blob_id')
-        resource.render_GET(request)
-
+        yield backend.read_blob('user', 'blob_id')
+        open.assert_called_once_with('path')
         backend._get_path.assert_called_once_with('user', 'blob_id', '')
-        ctype = 'application/octet-stream'
-        _blobs.static.File.assert_called_once_with('path', defaultType=ctype)
-        render_mock.render_GET.assert_called_once_with(request)
 
     @pytest.mark.usefixtures("method_tmpdir")
     @mock.patch.object(os.path, 'isfile')