diff --git a/src/linkahead/__init__.py b/src/linkahead/__init__.py
index 3a8c5ba39c88deaa5dc945135e3828945fd39d58..4462974cdcc8e1e9e8bf7108076da7c352170e46 100644
--- a/src/linkahead/__init__.py
+++ b/src/linkahead/__init__.py
@@ -42,7 +42,7 @@ from .common.datatype import (BOOLEAN, DATETIME, DOUBLE, FILE, INTEGER, LIST,
                               REFERENCE, TEXT)
 # Import of the basic  API classes:
 from .common.models import (ACL, ALL, FIX, NONE, OBLIGATORY, RECOMMENDED,
-                            SUGGESTED, Container, DropOffBox, Entity, File,
+                            SUGGESTED, Container, Entity, File,
                             Info, Message, Permissions, Property, Query,
                             QueryTemplate, Record, RecordType, delete,
                             execute_query, get_global_acl,
diff --git a/src/linkahead/common/models.py b/src/linkahead/common/models.py
index 38c1349067fce68dc3dc0311dc621bd0e383d4b0..23389f039f3f802028394890b0830fd3e2541842 100644
--- a/src/linkahead/common/models.py
+++ b/src/linkahead/common/models.py
@@ -202,6 +202,10 @@ class Entity:
 
         return self._wrapped_entity.size
 
+    @size.setter
+    def size(self, new_size):
+        self._size = new_size if new_size is None else int(new_size)
+
     @property
     def id(self):
         if self.__id is not None:
@@ -252,7 +256,17 @@ class Entity:
 
     @property
     def checksum(self):
-        return self._checksum
+        if self._checksum is not None:
+            return self._checksum
+
+        if self._wrapped_entity is None:
+            return None
+
+        return self._wrapped_entity._checksum
+
+    @checksum.setter
+    def checksum(self, new_checksum):
+        self._checksum = new_checksum
 
     @description.setter
     def description(self, new_description):
@@ -293,14 +307,16 @@ class Entity:
 
     @property
     def thumbnail(self):
-        if self.__thumbnail is not None or self._wrapped_entity is None:
-            return self.__thumbnail
-
-        return self._wrapped_entity.thumbnail
+        warn(DeprecationWarning(
+            "The thumbnail feature has been removed from the CaosDB server "
+            "API"))
+        return None
 
     @thumbnail.setter
     def thumbnail(self, new_thumbnail):
-        self.__thumbnail = new_thumbnail
+        warn(DeprecationWarning(
+            "The thumbnail feature has been removed from the CaosDB server "
+            "API"))
 
     @property
     def file(self):
@@ -315,14 +331,16 @@ class Entity:
 
     @property
     def pickup(self):
-        if self.__pickup is not None or self._wrapped_entity is None:
-            return self.__pickup
-
-        return self._wrapped_entity.pickup
+        warn(DeprecationWarning(
+            "The drop-off/pickup feature has been removed from the CaosDB "
+            "server API"))
+        return None
 
     @pickup.setter
     def pickup(self, new_pickup):
-        self.__pickup = new_pickup
+        warn(DeprecationWarning(
+            "The drop-off/pickup feature has been removed from the CaosDB "
+            "server API"))
 
     def grant(self, realm=None, username=None, role=None,
               permission=None, priority=False, revoke_denial=True):
@@ -1213,8 +1231,8 @@ out: List[Entity]
         if self.file is not None and local_serialization:
             xml.set("file", self.file)
 
-        if self._checksum is not None:
-            xml.set("checksum", self._checksum)
+        if self.checksum is not None:
+            xml.set("checksum", self.checksum)
 
         if self.size is not None:
             xml.set("size", str(self.size))
@@ -1992,35 +2010,35 @@ class File(Record):
 
     """This class represents LinkAhead's file entities.
 
-    For inserting a new file to the server, `path` gives the new location, and
-    (exactly?) one of `file` and `pickup` should (must?) be given to specify the
-    source of the file.
-
-    Symlinking from the "extroot" file system is not supported by this API yet,
-    it can be done manually using the `InsertFilesInDir` flag.  For sample code,
-    look at `test_files.py` in the Python integration tests of the
-    `load_files.py` script in the advanced user tools.
-
-    @param name: A name for this file record (That's an entity name - not to be
-        confused with the last segment of the files path).
-    @param id: An ID.
-    @param description: A description for this file record.
-    @param path: The complete path, including the file name, of the file in the
-        server's "caosroot" file system.
-    @param file: A local path or python file object.  The file designated by
-        this argument will be uploaded to the server via HTTP.
-    @param pickup: A file/folder in the DropOffBox (the server will move that
-        file into its "caosroot" file system).
-    @param thumbnail: (Local) filename to a thumbnail for this file.
-    @param properties: A list of properties for this file record. @todo is this
-        implemented?
-    @param from_location: Deprecated, use `pickup` instead.
+    For inserting a new file to the server or updating an existent one.
+    `path` gives the new location. `file` specifies the (local) file which is
+    to be uploaded. It is mandatory for insertions, but optionally for updates.
 
+    Parameters
+    ----------
+    name : str
+        A name for this file record (That's an entity name - not to be confused
+        with the last segment of the files path).
+    id : int
+        An ID.
+    description : str
+        A description for this file record.
+    path : str
+        The complete path, including the file name, of the file in the server's
+        virtual file system.
+    file : str or readable
+        A local path or python file object.  The file designated by this
+        argument will be uploaded to the server via HTTP.
+    pickup : str
+        deprecated.
+    thumbnail : str
+        deprecated.
     """
 
-    def __init__(self, name=None, id=None, description=None,  # @ReservedAssignment
-                 path=None, file=None, pickup=None,  # @ReservedAssignment
-                 thumbnail=None, from_location=None):
+    def __init__(self, name=None, id=None, description=None,
+                 path=None, file=None, pickup=None,
+                 thumbnail=None):
+
         Record.__init__(self, id=id, name=name, description=description)
         self.role = "File"
         self.datatype = None
@@ -2030,16 +2048,15 @@ class File(Record):
 
         # local file path or pointer to local file
         self.file = file
-        self.thumbnail = thumbnail
-
-        self.pickup = pickup
-
-        if from_location is not None:
+        if thumbnail is not None:
             warn(DeprecationWarning(
-                "Param `from_location` is deprecated, use `pickup instead`."))
+                "The thumbnail feature has been removed from the CaosDB "
+                "server API"))
 
-        if self.pickup is None:
-            self.pickup = from_location
+        if pickup is not None:
+            warn(DeprecationWarning(
+                "The drop-off/pickup feature has been removed from the CaosDB "
+                "server API"))
 
     def to_xml(self, xml=None, add_properties=ALL, local_serialization=False):
         """Convert this file to an xml element.
@@ -2053,7 +2070,7 @@ class File(Record):
         return Entity.to_xml(self, xml=xml, add_properties=add_properties,
                              local_serialization=local_serialization)
 
-    def download(self, target=None):
+    def download(self, target=None, check_hash=True):
         """Download this file-entity's actual file from the file server. It
         will be stored to the target or will be hold as a temporary file.
 
@@ -2066,16 +2083,16 @@ class File(Record):
             file_ = open(target, 'wb')
         else:
             file_ = NamedTemporaryFile(mode='wb', delete=False)
-        checksum = File.download_from_path(file_, self.path)
+        checksum = File._download_from_path(file_, self.path)
 
-        if self._checksum is not None and self._checksum.lower() != checksum.hexdigest().lower():
+        if check_hash and self.checksum is not None and self.checksum.lower() != checksum:
             raise ConsistencyError(
                 "The downloaded file had an invalid checksum. Maybe the download did not finish?")
 
         return file_.name
 
     @staticmethod
-    def download_from_path(target_file, path):
+    def _download_from_path(target_file, path):
 
         _log_request("GET (download): " + path)
         response = get_connection().download_file(path)
@@ -2089,46 +2106,27 @@ class File(Record):
             data = response.read(8000)
         target_file.close()
 
-        return checksum
+        return checksum.hexdigest().lower()
 
     @staticmethod
-    def _get_checksum(files):
-        import locale
-
-        if hasattr(files, "name"):
-            return File._get_checksum_single_file(files.name)
+    def _get_checksum(file):
+        if hasattr(file, "name"):
+            file_name = file.name
         else:
-            if isdir(files):
-                checksumappend = ""
-
-                for child in sorted(listdir(files),
-                                    key=cmp_to_key(locale.strcoll)):
-
-                    if isdir(files + '/' + child):
-                        checksumappend += child
-                    checksumappend += File._get_checksum(files + "/" + child)
-                checksum = sha512()
-                checksum.update(checksumappend.encode('utf-8'))
+            file_name = file
 
-                return checksum.hexdigest()
-            else:
-                return File._get_checksum_single_file(files)
-
-    @staticmethod
-    def _get_checksum_single_file(single_file):
-        _file = open(single_file, 'rb')
-        data = _file.read(1000)
         checksum = sha512()
-
-        while data:
-            checksum.update(data)
+        with open(file_name, 'rb') as _file:
             data = _file.read(1000)
-        _file.close()
 
-        return checksum.hexdigest()
+            while data:
+                checksum.update(data)
+                data = _file.read(1000)
+
+        return checksum.hexdigest().lower()
 
     def add_property(self, property=None, id=None, name=None, description=None, datatype=None,
-                     value=None, unit=None, importance=FIX, inheritance=FIX):  # @ReservedAssignment
+                     value=None, unit=None, importance=FIX, inheritance=FIX):
         """See ``Entity.add_property``."""
 
         return super().add_property(
@@ -3618,8 +3616,6 @@ class Container(list):
 
             if hasattr(entity, '_upload') and entity._upload is not None:
                 entity_xml.set("upload", entity._upload)
-            elif hasattr(entity, 'pickup') and entity.pickup is not None:
-                entity_xml.set("pickup", entity.pickup)
 
             insert_xml.append(entity_xml)
 
@@ -3690,20 +3686,18 @@ class Container(list):
                 part.filename = entity._upload
             http_parts.append(part)
 
-            if entity.thumbnail is not None:
-                part = MultipartParam.from_file(paramname=hex(
-                    randint(0, sys.maxsize)), filename=entity.thumbnail)
-                part.filename = entity._upload + ".thumbnail"
-                http_parts.append(part)
+        elif isinstance(entity, File) and hasattr(entity, "file") and entity.file is None:
+            entity._upload = None
         else:
+            entity._upload = None
             entity._checksum = None
 
     def insert(self, strict=False, raise_exception_on_error=True,
                unique=True, sync=True, flags=None):
-        """Insert this file entity into LinkAhead. A successful insertion will
-        generate a new persistent ID for this entity. This entity can be
-        identified, retrieved, updated, and deleted via this ID until it has
-        been deleted.
+        """Insert these entities into CaosDB.
+
+        A successful insertion will generate a persistent ID for the new entities. These entities can be
+        identified, retrieved, updated, and deleted via their ID until they have  been deleted.
 
         If the insertion fails, a LinkAheadException will be raised. The server will have returned at
         least one error-message describing the reason why it failed in that case (call
@@ -3768,8 +3762,6 @@ class Container(list):
 
             if hasattr(entity, '_upload') and entity._upload is not None:
                 entity_xml.set("upload", entity._upload)
-            elif hasattr(entity, 'pickup') and entity.pickup is not None:
-                entity_xml.set("pickup", entity.pickup)
             insert_xml.append(entity_xml)
 
         if len(self) > 0 and len(insert_xml) < 1:
@@ -4547,43 +4539,6 @@ def execute_query(q, unique=False, raise_exception_on_error=True, cache=True,
                          cache=cache, page_length=page_length)
 
 
-class DropOffBox(list):
-    def __init__(self, *args, **kwargs):
-        warn(DeprecationWarning(
-                "The DropOffBox is deprecated and will be removed in future."))
-        super().__init__(*args, **kwargs)
-
-    path = None
-
-    def sync(self):
-        c = get_connection()
-        _log_request("GET: Info")
-        http_response = c.retrieve(["Info"])
-        body = http_response.read()
-        _log_response(body)
-
-        xml = etree.fromstring(body)
-
-        for child in xml:
-            if child.tag.lower() == "stats":
-                infoelem = child
-
-                break
-
-        for child in infoelem:
-            if child.tag.lower() == "dropoffbox":
-                dropoffboxelem = child
-
-                break
-        del self[:]
-        self.path = dropoffboxelem.get('path')
-
-        for f in dropoffboxelem:
-            self.append(f.get('path'))
-
-        return self
-
-
 class UserInfo():
 
     def __init__(self, xml):