diff --git a/package-lock.json b/package-lock.json
index 69b9218930ce48df2966dfa84d0d0a31786b6d14..3e6f31cba2658c2d4d48546718a28bce8af484f9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1896,9 +1896,9 @@
       }
     },
     "@popperjs/core": {
-      "version": "2.5.4",
-      "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.5.4.tgz",
-      "integrity": "sha512-ZpKr+WTb8zsajqgDkvCEWgp6d5eJT6Q63Ng2neTbzBO76Lbe91vX/iVIW9dikq+Fs3yEo+ls4cxeXABD2LtcbQ=="
+      "version": "2.6.0",
+      "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.6.0.tgz",
+      "integrity": "sha512-cPqjjzuFWNK3BSKLm0abspP0sp/IGOli4p5I5fKFAzdS8fvjdOwDCfZqAaIiXd9lPkOWi3SUUfZof3hEb7J/uw=="
     },
     "@restart/context": {
       "version": "2.1.4",
@@ -1906,12 +1906,12 @@
       "integrity": "sha512-INJYZQJP7g+IoDUh/475NlGiTeMfwTXUEr3tmRneckHIxNolGOW9CTq83S8cxq0CgJwwcMzMJFchxvlwe7Rk8Q=="
     },
     "@restart/hooks": {
-      "version": "0.3.25",
-      "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.3.25.tgz",
-      "integrity": "sha512-m2v3N5pxTsIiSH74/sb1yW8D9RxkJidGW+5Mfwn/lHb2QzhZNlaU1su7abSyT9EGf0xS/0waLjrf7/XxQHUk7w==",
+      "version": "0.3.26",
+      "resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.3.26.tgz",
+      "integrity": "sha512-7Hwk2ZMYm+JLWcb7R9qIXk1OoUg1Z+saKWqZXlrvFwT3w6UArVNWgxYOzf+PJoK9zZejp8okPAKTctthhXLt5g==",
       "requires": {
-        "lodash": "^4.17.15",
-        "lodash-es": "^4.17.15"
+        "lodash": "^4.17.20",
+        "lodash-es": "^4.17.20"
       }
     },
     "@rollup/plugin-node-resolve": {
@@ -2462,9 +2462,9 @@
       "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug=="
     },
     "@types/react": {
-      "version": "16.9.56",
-      "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.56.tgz",
-      "integrity": "sha512-gIkl4J44G/qxbuC6r2Xh+D3CGZpJ+NdWTItAPmZbR5mUS+JQ8Zvzpl0ea5qT/ZT3ZNTUcDKUVqV3xBE8wv/DyQ==",
+      "version": "16.14.3",
+      "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.3.tgz",
+      "integrity": "sha512-zPrXn03hmPYqh9DznqSFQsoRtrQ4aHgnZDO+hMGvsE/PORvDTdJCHQ6XvJV31ic+0LzF73huPFXUb++W6Kri0Q==",
       "requires": {
         "@types/prop-types": "*",
         "csstype": "^3.0.2"
@@ -3848,6 +3848,11 @@
       "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
       "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
     },
+    "bootstrap": {
+      "version": "4.5.3",
+      "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.5.3.tgz",
+      "integrity": "sha512-o9ppKQioXGqhw8Z7mah6KdTYpNQY//tipnkxppWhPbiSWdD+1raYsnhwEZjkTHYbGee4cVQ0Rx65EhOY/HNLcQ=="
+    },
     "brace-expansion": {
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -5050,9 +5055,9 @@
       }
     },
     "csstype": {
-      "version": "3.0.5",
-      "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.5.tgz",
-      "integrity": "sha512-uVDi8LpBUKQj6sdxNaTetL6FpeCqTjOvAQuQUa/qAqq8oOd4ivkbhgnqayl0dnPal8Tb/yB1tF+gOvCBiicaiQ=="
+      "version": "3.0.6",
+      "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.6.tgz",
+      "integrity": "sha512-+ZAmfyWMT7TiIlzdqJgjMb7S4f1beorDbWbsocyK4RaiqA5RTX3K14bnBWmmA9QEM0gRdsjyyrEmcyga8Zsxmw=="
     },
     "cyclist": {
       "version": "1.0.1",
@@ -7925,6 +7930,11 @@
       "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
       "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw=="
     },
+    "immediate": {
+      "version": "3.0.6",
+      "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
+      "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps="
+    },
     "immer": {
       "version": "7.0.9",
       "resolved": "https://registry.npmjs.org/immer/-/immer-7.0.9.tgz",
@@ -8021,9 +8031,9 @@
       "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
     },
     "ini": {
-      "version": "1.3.5",
-      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
-      "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
+      "version": "1.3.8",
+      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+      "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
     },
     "inquirer": {
       "version": "7.3.3",
@@ -10329,6 +10339,41 @@
         "object.assign": "^4.1.1"
       }
     },
+    "jszip": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.2.0.tgz",
+      "integrity": "sha512-4WjbsaEtBK/DHeDZOPiPw5nzSGLDEDDreFRDEgnoMwmknPjTqa+23XuYFk6NiGbeiAeZCctiQ/X/z0lQBmDVOQ==",
+      "requires": {
+        "lie": "~3.3.0",
+        "pako": "~1.0.2",
+        "readable-stream": "~2.3.6",
+        "set-immediate-shim": "~1.0.1"
+      },
+      "dependencies": {
+        "readable-stream": {
+          "version": "2.3.7",
+          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+          "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+          "requires": {
+            "core-util-is": "~1.0.0",
+            "inherits": "~2.0.3",
+            "isarray": "~1.0.0",
+            "process-nextick-args": "~2.0.0",
+            "safe-buffer": "~5.1.1",
+            "string_decoder": "~1.1.1",
+            "util-deprecate": "~1.0.1"
+          }
+        },
+        "string_decoder": {
+          "version": "1.1.1",
+          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+          "requires": {
+            "safe-buffer": "~5.1.0"
+          }
+        }
+      }
+    },
     "killable": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
@@ -10383,6 +10428,14 @@
         "type-check": "~0.4.0"
       }
     },
+    "lie": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
+      "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
+      "requires": {
+        "immediate": "~3.0.5"
+      }
+    },
     "lines-and-columns": {
       "version": "1.1.6",
       "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz",
@@ -10443,9 +10496,9 @@
       "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
     },
     "lodash-es": {
-      "version": "4.17.15",
-      "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.15.tgz",
-      "integrity": "sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ=="
+      "version": "4.17.20",
+      "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.20.tgz",
+      "integrity": "sha512-JD1COMZsq8maT6mnuz1UMV0jvYD0E0aUsSOdrr1/nAG3dhqQXwRRgeW0cSqH1U43INKcqxaiVIQNOUDld7gRDA=="
     },
     "lodash._reinterpolate": {
       "version": "3.0.0",
@@ -14556,6 +14609,11 @@
       "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
       "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
     },
+    "set-immediate-shim": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
+      "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E="
+    },
     "set-value": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
@@ -16007,12 +16065,12 @@
       "dev": true
     },
     "uncontrollable": {
-      "version": "7.1.1",
-      "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.1.1.tgz",
-      "integrity": "sha512-EcPYhot3uWTS3w00R32R2+vS8Vr53tttrvMj/yA1uYRhf8hbTG2GyugGqWDY0qIskxn0uTTojVd6wPYW9ZEf8Q==",
+      "version": "7.2.1",
+      "resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz",
+      "integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==",
       "requires": {
         "@babel/runtime": "^7.6.3",
-        "@types/react": "^16.9.11",
+        "@types/react": ">=16.9.11",
         "invariant": "^2.2.4",
         "react-lifecycles-compat": "^3.0.4"
       }
diff --git a/package.json b/package.json
index 115952d7fa64ccbfeea9327502ebe0f3aead1531..fef55b15322cae2989d9ebf1206936db583ca439 100644
--- a/package.json
+++ b/package.json
@@ -12,6 +12,8 @@
   "version": "0.1.0",
   "private": true,
   "dependencies": {
+    "bootstrap": "4.5",
+    "jszip": "3.2.0",
     "react": "^17.0.1",
     "react-bootstrap": "1.4.0",
     "react-dom": "^17.0.1",
diff --git a/src/components/experiment-list/import-experiment-buttons.css b/src/components/experiment-list/import-experiment-buttons.css
new file mode 100644
index 0000000000000000000000000000000000000000..429b61bbeb0046a0a3218f0b358a3fcd7cf82cd2
--- /dev/null
+++ b/src/components/experiment-list/import-experiment-buttons.css
@@ -0,0 +1,18 @@
+.import-popup {
+    width: 33.3%;
+    padding: 15px;
+    left: 0;
+    margin-left: 33.3%;
+    border: 1px solid #ccc;
+    border-radius: 10px;
+    background: white;
+    position: absolute;
+    top: 15%;
+    box-shadow: 5px 5px 5px #000;
+    z-index: 10001;
+  }
+  
+  #import-buttons {
+    vertical-align: middle;
+    margin: auto 0;
+  }
\ No newline at end of file
diff --git a/src/components/experiment-list/import-experiment-buttons.js b/src/components/experiment-list/import-experiment-buttons.js
new file mode 100644
index 0000000000000000000000000000000000000000..8129213a7b674a8fd7fa8801d7e79a026147f865
--- /dev/null
+++ b/src/components/experiment-list/import-experiment-buttons.js
@@ -0,0 +1,175 @@
+import React from 'react';
+
+import { FaFolder, FaFileArchive, FaAudible } from 'react-icons/fa';
+import { ButtonGroup, Button } from 'react-bootstrap';
+
+import ImportExperimentService from '../../services/experiments/files/import-experiment-service.js';
+import ExperimentStorageService from '../../services/experiments/files/experiment-storage-service.js';
+import './experiment-list-element.css';
+import './import-experiment-buttons.css';
+export default class ImportExperimentButtons extends React.Component {
+  constructor(props) {
+    super(props);
+    this.state = {};
+  }
+
+  importFolderPopupClick() {
+    this.setState({
+      importFolderResponse : undefined
+    });
+  }
+
+  importZipPopupClick() {
+    this.setState({
+      importZipResponses : undefined
+    });
+  }
+
+  scanStoragePopupClick() {
+    this.setState({
+      scanStorageResponse : undefined
+    });
+  }
+
+  importExperimentFolderChange(event) {
+    this.setState({
+      isImporting : true
+    });
+    ImportExperimentService.instance
+      .importExperimentFolder(event)
+      .then(async response => {
+        this.setState({
+          importFolderResponse : await response.json()
+        });
+        ExperimentStorageService.instance.getExperiments(true);
+      })
+      .finally(() => {
+        this.setState({
+          isImporting : false
+        });
+      });
+  };
+
+  importZippedExperimentChange(event) {
+    this.setState({
+      isImporting : true
+    });
+    ImportExperimentService.instance
+      .importZippedExperiment(event)
+      .then(async responses => {
+        this.setState({
+          importZipResponses : await responses
+        });
+        ExperimentStorageService.instance.getExperiments(true);
+      })
+      .finally(() => {
+        this.setState({
+          isImporting : false
+        });
+      });
+  };
+
+  scanStorageClick() {
+    this.setState({
+      isImporting : true
+    });
+    ImportExperimentService.instance
+      .scanStorage()
+      .then(async response => {
+        this.setState({
+          scanStorageResponse : await response
+        });
+        ExperimentStorageService.instance.getExperiments(true);
+      })
+      .finally(() => {
+        this.setState({
+          isImporting : false
+        });
+      });
+  }
+
+  render() {
+    return (
+      <div>
+        {/* Import folder pop-up */}
+        {this.state.importFolderResponse
+          ? <div className="import-popup">
+            <div variant="success">
+              <p>The experiment folder
+                <b>{' ' + this.state.importFolderResponse.zipBaseFolderName}</b> has been succesfully imported as
+                <b>{' ' + this.state.importFolderResponse.destFolderName}</b>.
+              </p>
+            </div>
+            <div className="text-right">
+              <Button variant="success" onClick={() => this.importFolderPopupClick()}>Got it!</Button>
+            </div>
+          </div>
+          : null
+        }
+
+        {/* Import zip pop-up */}
+        {this.state.importZipResponses
+          ? <div className="import-popup">
+            <div>
+              <p>{this.state.importZipResponses.numberOfZips} successfully imported zip files.</p>
+            </div>
+            <p>The following experiments folders</p>
+            <p><b>{this.state.importZipResponses.zipBaseFolderName.join(', ')}</b></p>
+            <p>have been successfully imported as:</p>
+            <p><b>{this.state.importZipResponses.destFolderName.join(', ')}.</b></p>
+            <div className="text-right">
+              <Button variant="success" onClick={() => this.importZipPopupClick()}>Got it!</Button>
+            </div>
+          </div>
+          : null
+        }
+
+        {/* Scan pop-up */}
+        {this.state.scanStorageResponse
+          ? <div className="import-popup">
+            <div>
+              <p>{this.state.scanStorageResponse.addedFoldersNumber} added folders,
+                {' ' + this.state.scanStorageResponse.deletedFoldersNumber} deleted folders.</p>
+            </div>
+            <p>Added:</p>
+            <p><b>{this.state.scanStorageResponse.addedFolders !== ''
+              ? this.state.scanStorageResponse.addedFolders
+              : 'none' }
+            </b></p>
+            <p>Deleted:</p>
+            <p><b>{this.state.scanStorageResponse.deletedFolders !== ''
+              ? this.state.scanStorageResponse.deletedFolders
+              : 'none' }</b></p>
+            <div className="text-right">
+              <Button variant="success" onClick={() => this.scanStoragePopupClick()}>Got it!</Button>
+            </div>
+          </div>
+          : null
+        }
+
+        {/* Import buttons */}
+        <div className="list-entry-buttons flex-container center">
+          <input id="folder" type="file" style={{display:'none'}}
+            multiple directory="" webkitdirectory=""
+            onChange={(event) => this.importExperimentFolderChange(event)}/>
+          <input id="zip" type="file" style={{display:'none'}}
+            multiple accept='.zip'
+            onChange={(event) => this.importZippedExperimentChange(event)}/>
+          {!this.state.isImporting
+            ? <ButtonGroup role="group">
+              <Button variant="outline-dark">
+                <label htmlFor="folder"><FaFolder/> Import folder</label>
+              </Button>
+              <Button variant="outline-dark">
+                <label htmlFor="zip"><FaFileArchive/> Import zip</label>
+              </Button >
+              <Button variant="outline-dark" onClick={() => this.scanStorageClick()}>
+                <FaAudible/> Scan Storage
+              </Button>
+            </ButtonGroup>
+            : null}
+        </div>
+      </div>
+    );
+  }
+}
\ No newline at end of file
diff --git a/src/components/experiment-overview/experiment-overview.js b/src/components/experiment-overview/experiment-overview.js
index a8d1146854b3c85a8a584aa8b02f841ac63720ba..afa1f1becfd18912770efcf1a67559d89472b2a9 100644
--- a/src/components/experiment-overview/experiment-overview.js
+++ b/src/components/experiment-overview/experiment-overview.js
@@ -7,6 +7,7 @@ import PublicExperimentsService from '../../services/experiments/files/public-ex
 import ExperimentServerService from '../../services/experiments/execution/server-resources-service.js';
 import ExperimentExecutionService from '../../services/experiments/execution/experiment-execution-service.js';
 
+import ImportExperimentButtons from '../experiment-list/import-experiment-buttons.js';
 import ExperimentList from '../experiment-list/experiment-list.js';
 import NrpHeader from '../nrp-header/nrp-header.js';
 
@@ -128,6 +129,7 @@ export default class ExperimentOverview extends React.Component {
 
           {/* My Experiments */}
           <TabPanel>
+            <ImportExperimentButtons />
             <ExperimentList experiments={this.state.storageExperiments}
               availableServers={this.state.availableServers}
               startingExperiment={this.state.startingExperiment} />
diff --git a/src/index.js b/src/index.js
index ef2edf8ea3fc42258464231e29140c8723458c1e..33f3dd6b06a99231aa04113f545f3f2c34dd0955 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,6 +1,7 @@
 import React from 'react';
 import ReactDOM from 'react-dom';
 import './index.css';
+import 'bootstrap/dist/css/bootstrap.min.css';
 import App from './App';
 import reportWebVitals from './reportWebVitals';
 
diff --git a/src/services/error-handler-service.js b/src/services/error-handler-service.js
index ccc8bca5b87cb7301c834f3a8c5843ab4cfbc750..9a62e91d44dda85327f07733d89f962a716e43b6 100644
--- a/src/services/error-handler-service.js
+++ b/src/services/error-handler-service.js
@@ -28,6 +28,11 @@ class ErrorHandlerService {
     //TODO: needs proper UI implementation
     console.error(error);
   }
+
+  displayError (error){
+    //TODO: needs proper implementation
+    console.error(error.type + error.message);
+  }
 }
 
 export default ErrorHandlerService;
diff --git a/src/services/experiments/files/experiment-storage-service.js b/src/services/experiments/files/experiment-storage-service.js
index 14fd55bfe59b574135be7c769b34fb04973620ab..9fdd009e4b5345b64d0487276089302886654850 100644
--- a/src/services/experiments/files/experiment-storage-service.js
+++ b/src/services/experiments/files/experiment-storage-service.js
@@ -69,6 +69,8 @@ class ExperimentStorageService extends HttpService {
   async getExperiments(forceUpdate = false) {
     if (!this.experiments || forceUpdate) {
       let experimentList = await (await this.httpRequestGET(storageExperimentsURL)).json();
+      // filter out experiments with incomplete configuration (probably storage corruption)
+      experimentList = experimentList.filter(experiment => experiment.configuration.experimentFile);
       this.sortExperiments(experimentList);
       await this.fillExperimentDetails(experimentList);
       this.experiments = experimentList;
diff --git a/src/services/experiments/files/import-experiment-service.js b/src/services/experiments/files/import-experiment-service.js
new file mode 100644
index 0000000000000000000000000000000000000000..7d00ffc80e75a1cff50debe545e829c2fc034983
--- /dev/null
+++ b/src/services/experiments/files/import-experiment-service.js
@@ -0,0 +1,175 @@
+import { HttpService } from '../../http-service.js';
+import ErrorHandlerService from '../../error-handler-service.js';
+import JSZip from 'jszip';
+
+import endpoints from '../../proxy/data/endpoints.json';
+import config from '../../../config.json';
+const importExperimentURL = `${config.api.proxy.url}${endpoints.proxy.storage.importExperiment.url}`;
+const scanStorageURL = `${config.api.proxy.url}${endpoints.proxy.storage.scanStorage.url}`;
+
+let _instance = null;
+const SINGLETON_ENFORCER = Symbol();
+const options = {
+  mode: 'cors', // no-cors, *cors, same-origin
+  cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
+  credentials: 'same-origin', // include, *same-origin, omit
+  headers: {
+    'Content-Type': 'application/octet-stream',
+    Referer: 'http://localhost:9000/'
+  },
+  // redirect: manual, *follow, error
+  redirect: 'follow',
+  // referrerPolicy: no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin,
+  // strict-origin, strict-origin-when-cross-origin, unsafe-url
+  referrerPolicy: 'no-referrer',
+  //body: JSON.stringify(data) // body data type must match "Content-Type" header
+  method: 'POST'
+};
+
+export default class ImportExperimentService extends HttpService {
+  constructor(enforcer) {
+    super();
+    if (enforcer !== SINGLETON_ENFORCER) {
+      throw new Error('Use ' + this.constructor.name + '.instance');
+    }
+  }
+
+  static get instance() {
+    if (_instance == null) {
+      _instance = new ImportExperimentService(SINGLETON_ENFORCER);
+    }
+
+    return _instance;
+  }
+
+  getImportZipResponses(responses) {
+    let importZipResponses = {
+      zipBaseFolderName: [],
+      destFolderName: []
+    };
+    importZipResponses.numberOfZips = responses.length;
+    responses.forEach(async response =>{
+      response = await response.json();
+      importZipResponses['zipBaseFolderName'].push(response['zipBaseFolderName']);
+      importZipResponses['destFolderName'].push(response['destFolderName']);
+    });
+    return importZipResponses;
+  }
+
+  async getScanStorageResponse(response) {
+    response = await response.json();
+    let scanStorageResponse = {};
+    ['deletedFolders', 'addedFolders'].forEach(name => {
+      scanStorageResponse[`${name}Number`] = response[name].length;
+      scanStorageResponse[name] = response[name].join(', ');
+    });
+    return scanStorageResponse;
+  }
+
+  async scanStorage() {
+    return this.httpRequestPOST(scanStorageURL)
+      .then(response => this.getScanStorageResponse(response))
+      .catch(error => ErrorHandlerService.instance.displayError(error));
+  }
+
+  async zipExperimentFolder(event) {
+    let zip = new JSZip();
+    let files = event.target.files;
+    if (files.length === 0){
+      return; // The folder upload was aborted by user
+    }
+    let promises = [];
+    Array.from(files).forEach(file => {
+      promises.push(
+        new Promise((resolve, reject) => {
+          let reader = new FileReader();
+          reader.onerror = error => {
+            reader.abort();
+            return reject(error);
+          };
+          reader.onload = f =>
+            resolve([file.webkitRelativePath, f.target.result]);
+          if (
+            file.type.startsWith('image') ||
+            file.type === 'application/zip' ||
+            file.webkitRelativePath.split('.').pop() === 'h5'
+          ) {
+            reader.readAsArrayBuffer(file);
+          }
+          else {
+            reader.readAsText(file);
+          }
+        })
+          .then(([filepath, filecontent]) =>
+            Promise.resolve(
+              zip.file(filepath, filecontent, { createFolders: true })
+            )
+          )
+          .catch(error => {
+            ErrorHandlerService.instance.displayError(error);
+            return Promise.reject(error);
+          })
+      );
+    });
+
+    return Promise.all(promises)
+      .then(() => zip.generateAsync({ type: 'blob' }))
+      .catch(error => {
+        ErrorHandlerService.instance.displayError(error);
+        return Promise.reject(error);
+      });
+  }
+
+  async importExperimentFolder(event) {
+    return this.zipExperimentFolder(event).then(async zipContent => {
+      return this.httpRequestPOST(importExperimentURL, zipContent, options)
+        .catch(error => ErrorHandlerService.instance
+          .displayError(error)
+        );
+    });
+  }
+
+  readZippedExperimentExperiment(event) {
+    let files = event.target.files;
+    let zipFiles = [];
+    Array.from(files).forEach(file => {
+      if (file.type !== 'application/zip') {
+        ErrorHandlerService.instance.displayError({
+          type : 'Import Error.',
+          message :`The file ${file.name} cannot be imported because it is not a zip file.`
+        });
+      }
+      else {
+        zipFiles.push(file);
+      }
+    });
+    let promises = zipFiles.map(zipFile => {
+      return new Promise(resolve => {
+        let reader = new FileReader();
+        reader.onload = f => resolve(f.target.result);
+        reader.readAsArrayBuffer(zipFile);
+      });
+    });
+    return Promise.all(promises);
+  }
+
+  importZippedExperiment(event) {
+    let promises = this.readZippedExperimentExperiment(event)
+      .then(zipContents =>
+        zipContents.map(zipContent =>
+          this.httpRequestPOST(importExperimentURL, zipContent, options)
+            .catch(error => {
+              ErrorHandlerService.instance.displayError(error);
+              return Promise.reject(error);
+            })
+        )
+      )
+      .then(responses =>
+        Promise
+          .all(responses)
+          .then(responses => this.getImportZipResponses(responses))
+      );
+    return promises;
+  }
+
+}
\ No newline at end of file
diff --git a/src/services/proxy/data/endpoints.json b/src/services/proxy/data/endpoints.json
index bf01f00031af2a2d34b346a4ae20b41414683183..2ab2653147217a8d0853ad87705cd1b8d10fbcb0 100644
--- a/src/services/proxy/data/endpoints.json
+++ b/src/services/proxy/data/endpoints.json
@@ -28,6 +28,12 @@
             },
             "experiments": {
                 "url": "/storage/experiments"
+            },
+            "importExperiment":{
+                "url": "/storage/importExperiment"
+            },
+            "scanStorage":{
+                "url":"/storage/scanStorage"
             }
         }
     }