diff --git a/app/corpora/routes.py b/app/corpora/routes.py
index bbe98090f5befca4a80de5ffa76de2d362fcb74d..57c14e651c0303ceae8103cd18dc3fde1b221b54 100644
--- a/app/corpora/routes.py
+++ b/app/corpora/routes.py
@@ -149,7 +149,7 @@ def create_corpus_file(corpus_id):
                 mimetype='application/vrt+xml',
                 corpus=corpus
             )
-        except OSError:
+        except (AttributeError, OSError):
             abort(500)
         corpus.status = CorpusStatus.UNPREPARED
         db.session.commit()
diff --git a/app/models.py b/app/models.py
index 6719ca72e3936d917cae9c1e808f2d7f41bd2249..21a64d356f3114100525751982d0e7cd1a58065c 100644
--- a/app/models.py
+++ b/app/models.py
@@ -91,6 +91,26 @@ class FileMixin:
             ),
             'mimetype': self.mimetype
         }
+    
+    @classmethod
+    def create(cls, file_storage, **kwargs):
+        filename = kwargs.pop('filename', file_storage.filename)
+        mimetype = kwargs.pop('mimetype', file_storage.mimetype)
+        obj = cls(
+            filename=secure_filename(filename),
+            mimetype=mimetype,
+            **kwargs
+        )
+        db.session.add(obj)
+        db.session.flush(objects=[obj])
+        db.session.refresh(obj)
+        try:
+            file_storage.save(obj.path)
+        except (AttributeError, OSError) as e:
+            current_app.logger.error(e)
+            db.session.rollback()
+            raise e
+        return obj
 # endregion mixins
 
 
@@ -691,26 +711,6 @@ class JobInput(FileMixin, HashidMixin, db.Model):
     def user_id(self):
         return self.job.user_id
 
-    @staticmethod
-    def create(input_file, **kwargs):
-        filename = kwargs.get('filename', input_file.filename)
-        mimetype = kwargs.get('mimetype', input_file.mimetype)
-        job_input = JobInput(
-            filename=secure_filename(filename),
-            mimetype=mimetype,
-            **kwargs
-        )
-        db.session.add(job_input)
-        db.session.flush(objects=[job_input])
-        db.session.refresh(job_input)
-        try:
-            input_file.save(job_input.path)
-        except OSError as e:
-            current_app.logger.error(e)
-            db.session.rollback()
-            raise e
-        return job_input
-
     def to_json(self, backrefs=False, relationships=False):
         _json = {
             'id': self.hashid,
@@ -766,26 +766,6 @@ class JobResult(FileMixin, HashidMixin, db.Model):
     def user_id(self):
         return self.job.user_id
 
-    @staticmethod
-    def create(input_file, **kwargs):
-        filename = kwargs.get('filename', input_file.filename)
-        mimetype = kwargs.get('mimetype', input_file.mimetype)
-        job_result = JobResult(
-            filename=secure_filename(filename),
-            mimetype=mimetype,
-            **kwargs
-        )
-        db.session.add(job_result)
-        db.session.flush(objects=[job_result])
-        db.session.refresh(job_result)
-        try:
-            input_file.save(job_result.path)
-        except OSError as e:
-            current_app.logger.error(e)
-            db.session.rollback()
-            raise e
-        return job_result
-
     def to_json(self, backrefs=False, relationships=False):
         _json = {
             'id': self.hashid,
@@ -1024,26 +1004,6 @@ class CorpusFile(FileMixin, HashidMixin, db.Model):
             _json['corpus'] = self.corpus.to_json(backrefs=True)
         return _json
 
-    @staticmethod
-    def create(input_file, **kwargs):
-        filename = kwargs.pop('filename', input_file.filename)
-        mimetype = kwargs.pop('mimetype', input_file.mimetype)
-        corpus_file = CorpusFile(
-            filename=secure_filename(filename),
-            mimetype=mimetype,
-            **kwargs,
-        )
-        db.session.add(corpus_file)
-        db.session.flush(objects=[corpus_file])
-        db.session.refresh(corpus_file)
-        try:
-            input_file.save(corpus_file.path)
-        except OSError as e:
-            current_app.logger.error(e)
-            db.session.rollback()
-            raise e
-        return corpus_file
-
 class Corpus(HashidMixin, db.Model):
     '''
     Class to define a corpus.
diff --git a/app/services/routes.py b/app/services/routes.py
index 9f5c81ef228676291bb525375a33b386eb9f2fb6..913acbb75deaaf85d69f0a62410d90061c2f6444 100644
--- a/app/services/routes.py
+++ b/app/services/routes.py
@@ -45,7 +45,7 @@ def file_setup_pipeline():
         for input_file in form.images.data:
             try:
                 JobInput.create(input_file, job=job)
-            except OSError:
+            except (AttributeError, OSError):
                 abort(500)
         job.status = JobStatus.SUBMITTED
         db.session.commit()
@@ -88,7 +88,7 @@ def tesseract_ocr_pipeline():
             abort(500)
         try:
             JobInput.create(form.pdf.data, job=job)
-        except OSError:
+        except (AttributeError, OSError):
             abort(500)
         job.status = JobStatus.SUBMITTED
         db.session.commit()
@@ -138,7 +138,7 @@ def transkribus_htr_pipeline():
             abort(500)
         try:
             JobInput.create(form.pdf.data, job=job)
-        except OSError:
+        except (AttributeError, OSError):
             abort(500)
         job.status = JobStatus.SUBMITTED
         db.session.commit()
@@ -187,7 +187,7 @@ def spacy_nlp_pipeline():
             abort(500)
         try:
             JobInput.create(form.txt.data, job=job)
-        except OSError:
+        except (AttributeError, OSError):
             abort(500)
         job.status = JobStatus.SUBMITTED
         db.session.commit()