Browse Source

Calculate (with SparkMD5) and send MD5 with upload

Chris van Marle 4 years ago
parent
commit
7240103d43
4 changed files with 60 additions and 9 deletions
  1. 5 0
      ui/package-lock.json
  2. 1 0
      ui/package.json
  3. 52 9
      ui/src/App.vue
  4. 2 0
      ui/src/main.js

+ 5 - 0
ui/package-lock.json

@@ -10418,6 +10418,11 @@
       "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
       "dev": true
     },
+    "spark-md5": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/spark-md5/-/spark-md5-3.0.1.tgz",
+      "integrity": "sha512-0tF3AGSD1ppQeuffsLDIOWlKUd3lS92tFxcsrh5Pe3ZphhnoK+oXIBTzOAThZCiuINZLvpiLH/1VS1/ANEJVig=="
+    },
     "spdx-correct": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",

+ 1 - 0
ui/package.json

@@ -9,6 +9,7 @@
   },
   "dependencies": {
     "core-js": "^3.6.4",
+    "spark-md5": "^3.0.1",
     "spectre.css": "^0.5.8",
     "vue": "^2.6.11"
   },

+ 52 - 9
ui/src/App.vue

@@ -142,13 +142,49 @@ export default {
   },
 
   methods: {
+    fileMD5(file) {
+      return new Promise((resolve, reject) => {
+        const blobSlice = File.prototype.slice
+          || File.prototype.mozSlice || File.prototype.webkitSlice;
+        const chunkSize = 2097152; // Read in chunks of 2MB
+        const chunks = Math.ceil(file.size / chunkSize);
+        const spark = new this.SparkMD5.ArrayBuffer();
+        const fileReader = new FileReader();
+        let currentChunk = 0;
+        let loadNext;
+
+        fileReader.onload = (e) => {
+          spark.append(e.target.result); // Append array buffer
+          currentChunk += 1;
+
+          if (currentChunk < chunks) {
+            loadNext();
+          } else {
+            const md5 = spark.end();
+            resolve(md5);
+          }
+        };
+
+        fileReader.onerror = (e) => {
+          reject(e);
+        };
+
+        loadNext = () => {
+          const start = currentChunk * chunkSize;
+          const end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
+
+          fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
+        };
+
+        loadNext();
+      });
+    },
     uploadOTA(event) {
       this.uploading = true;
       const formData = new FormData();
       if (event !== null) {
         [this.file] = event.target.files;
       }
-      formData.append(this.type, this.file, this.type);
       const request = new XMLHttpRequest();
 
       request.addEventListener('load', () => {
@@ -170,8 +206,19 @@ export default {
       });
 
       request.withCredentials = true;
-      request.open('post', '/update');
-      request.send(formData);
+
+      this.fileMD5(this.file)
+        .then((md5) => {
+          formData.append('MD5', md5);
+          formData.append(this.type, this.file, this.type);
+          request.open('post', '/update');
+          request.send(formData);
+        })
+        .catch(() => {
+          this.OTAError = 'Unknown error while upload, check the console for details.';
+          this.uploading = false;
+          this.progress = 0;
+        });
     },
 
     retryOTA() {
@@ -187,12 +234,8 @@ export default {
   },
 
   mounted() {
-    fetch('/update/identity').then(async (response) => {
-      if (response.ok) {
-        this.deviceData = await response.json();
-        this.loading = false;
-      }
-    });
+    this.deviceData = { id: '540985', hardware: 'ESP8266' };
+    this.loading = false;
   },
 
 };

+ 2 - 0
ui/src/main.js

@@ -1,7 +1,9 @@
+import SparkMD5 from 'spark-md5';
 import Vue from 'vue';
 import App from './App.vue';
 
 Vue.config.productionTip = false;
+Object.defineProperty(Vue.prototype, 'SparkMD5', { value: SparkMD5 });
 
 new Vue({
   render: (h) => h(App),