From 9efc1234dce422072a6107b5524db55a8d56b1e8 Mon Sep 17 00:00:00 2001
From: wataru <wataru@fdev.local.com>
Date: Sun, 30 Oct 2022 22:37:57 +0900
Subject: [PATCH] update

---
 demo/MMVCServerSIO.py  | 44 ++++++++++++++++++++++++++++--------------
 frontend/dist/index.js |  2 +-
 trainer/Dockerfile     |  2 +-
 3 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/demo/MMVCServerSIO.py b/demo/MMVCServerSIO.py
index 3ab31362..f83a45f5 100755
--- a/demo/MMVCServerSIO.py
+++ b/demo/MMVCServerSIO.py
@@ -150,6 +150,8 @@ if __name__ == thisFilename or args.colab == True:
         return {"result": "Index"}
     
 
+    UPLOAD_DIR = "model_upload_dir"
+    os.makedirs(UPLOAD_DIR)
     # Can colab receive post request "ONLY" at root path?
     @app_fastapi.post("/upload_model_file")
     async def upload_file(configFile:UploadFile = File(...), modelFile: UploadFile = File(...)):
@@ -157,37 +159,51 @@ if __name__ == thisFilename or args.colab == True:
             for file in [modelFile, configFile]:
                 filename = file.filename
                 fileobj = file.file
-                upload_dir = open(os.path.join(".", filename),'wb+')
+                upload_dir = open(os.path.join(UPLOAD_DIR, filename),'wb+')
                 shutil.copyfileobj(fileobj, upload_dir)
                 upload_dir.close()
-            namespace.loadModel(configFile.filename, modelFile.filename)                
+            namespace.loadModel(os.path.join(UPLOAD_DIR, configFile.filename), os.path.join(UPLOAD_DIR, modelFile.filename))                
             return {"uploaded files": f"{configFile.filename}, {modelFile.filename} "}
         return {"Error": "uploaded file is not found."}
 
 
-    @app_fastapi.get("/resumable")
-    async def get_resumble():
-        print("GET REQUSET")
-        raise HTTPException(status_code=404, detail="Not found")
 
-        return 'OK'
-
-    @app_fastapi.post("/resumable")
-    async def post_resumble(
+    @app_fastapi.post("/upload_file")
+    async def post_upload_file(
         file:UploadFile = File(...), 
         filename: str = Form(...)
         ):
 
-        print("resumableFilename", filename)
         if file and filename:
-            filename = file.filename + "_" + filename
             fileobj = file.file
-            upload_dir = open(os.path.join(".", filename),'wb+')
+            upload_dir = open(os.path.join(UPLOAD_DIR, filename),'wb+')
             shutil.copyfileobj(fileobj, upload_dir)
             upload_dir.close()
             return {"uploaded files": f"{filename} "}
         return {"Error": "uploaded file is not found."}
-        return 'OK'
+
+    @app_fastapi.post("/load_model")
+    async def post_load_model(
+        modelFilename: str = Form(...),
+        modelFilenameChunkNum: int = Form(...),
+        configFilename: str = Form(...)
+        ):
+
+        target_file_name = modelFilename
+        with open(os.path.join(UPLOAD_DIR, target_file_name), "ab") as target_file:
+            for i in range(modelFilenameChunkNum):
+                filename = f"{modelFilename}_{i}"
+                chunk_file_path = os.path.join(UPLOAD_DIR,filename)
+                stored_chunk_file = open(chunk_file_path, 'rb')
+                target_file.write(stored_chunk_file.read())
+                stored_chunk_file.close()
+                os.unlink(chunk_file_path)
+        target_file.close()
+        print(f'File saved to: {target_file_name}')
+
+        print(f'Load: {configFilename}, {target_file_name}')
+        namespace.loadModel(os.path.join(UPLOAD_DIR, configFilename), os.path.join(UPLOAD_DIR, target_file_name))
+        return {"File saved to": f"{target_file_name}"}
 
 
     @app_fastapi.post("/test")
diff --git a/frontend/dist/index.js b/frontend/dist/index.js
index 4fcd77a6..53692c7b 100755
--- a/frontend/dist/index.js
+++ b/frontend/dist/index.js
@@ -3913,7 +3913,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
 /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
 
 "use strict";
-eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"fetchTextResource\": () => (/* binding */ fetchTextResource),\n/* harmony export */   \"postVoice\": () => (/* binding */ postVoice),\n/* harmony export */   \"uploadModelProps\": () => (/* binding */ uploadModelProps),\n/* harmony export */   \"uploadModelPropsResumable\": () => (/* binding */ uploadModelPropsResumable)\n/* harmony export */ });\n/* provided dependency */ var Buffer = __webpack_require__(/*! buffer */ \"./node_modules/buffer/index.js\")[\"Buffer\"];\n// import Resumable from 'resumablejs'\n// import { file } from \"jszip\";\nconst fetchTextResource = async (url) => {\n    const res = await fetch(url, {\n        method: \"GET\"\n    });\n    const text = res.text();\n    return text;\n};\nconst postVoice = async (url, gpu, srcId, dstId, timestamp, buffer) => {\n    const obj = {\n        gpu, srcId, dstId, timestamp, buffer: Buffer.from(buffer).toString('base64')\n    };\n    const body = JSON.stringify(obj);\n    const res = await fetch(`${url}`, {\n        method: \"POST\",\n        headers: {\n            'Accept': 'application/json',\n            'Content-Type': 'application/json'\n        },\n        body: body\n    });\n    const receivedJson = await res.json();\n    const changedVoiceBase64 = receivedJson[\"changedVoiceBase64\"];\n    const buf = Buffer.from(changedVoiceBase64, \"base64\");\n    const ab = new ArrayBuffer(buf.length);\n    // console.log(\"RECIV\", buf.length)\n    const view = new Uint8Array(ab);\n    for (let i = 0; i < buf.length; ++i) {\n        view[i] = buf[i];\n    }\n    return ab;\n};\nconst uploadModelProps = (modelFile, configFile, onprogress) => {\n    const req = new XMLHttpRequest();\n    const formData = new FormData();\n    formData.append(\"modelFile\", modelFile);\n    formData.append(\"configFile\", configFile);\n    req.upload.onprogress = (ev) => {\n        const progress = Math.ceil(ev.loaded / ev.total * 10000 / 100);\n        console.log(\"Progress:\", ev.loaded, ev.total, progress);\n        onprogress(progress, ev.loaded == ev.total);\n    };\n    req.upload.onloadend = (ev) => {\n        console.log(\"Progress[END!]:\", ev.loaded, ev.total, Math.ceil(ev.loaded / ev.total * 10000 / 100));\n        onprogress(100, true);\n    };\n    req.open(\"POST\", '/upload_model_file');\n    req.send(formData);\n};\nconst uploadModelPropsResumable = async (modelFile, _configFile, _onprogress) => {\n    const size = 1024 * 1024;\n    // const size = modelFile.size / 10;\n    const fileChunks = [];\n    let index = 0; // index値\n    for (let cur = 0; cur < modelFile.size; cur += size) {\n        fileChunks.push({\n            hash: index++,\n            chunk: modelFile.slice(cur, cur + size),\n        });\n    }\n    console.log(\"FILE_CHUNKS:\", fileChunks);\n    while (true) {\n        const promises = [];\n        for (let i = 0; i < 10; i++) {\n            const chunk = fileChunks.shift();\n            if (!chunk) {\n                break;\n            }\n            const p = new Promise((resolve) => {\n                const formData = new FormData();\n                formData.append(\"file\", chunk.chunk);\n                formData.append(\"filename\", \"file_\" + chunk.hash);\n                const request = new Request('/resumable', {\n                    method: 'POST',\n                    body: formData,\n                });\n                fetch(request).then(async (response) => {\n                    console.log(await response.text());\n                    resolve();\n                });\n            });\n            promises.push(p);\n        }\n        await Promise.all(promises);\n    }\n    // for (const x of fileChunks) {\n    //     console.log(\"SEND CHUNK:\", x.hash)\n    //     const p = new Promise<void>((resolve, _reject) => {\n    //         // const req = new XMLHttpRequest();\n    //         const formData = new FormData();\n    //         formData.append(\"file\", x.chunk);\n    //         formData.append(\"filename\", \"file_\" + x.hash);\n    //         // req.upload.onprogress = (ev: ProgressEvent<EventTarget>) => {\n    //         //     const progress = Math.ceil(ev.loaded / ev.total * 10000 / 100)\n    //         //     console.log(\"Progress:\", ev.loaded, ev.total, progress)\n    //         //     // onprogress(progress, ev.loaded == ev.total)\n    //         // }\n    //         // req.upload.onloadend = (ev: ProgressEvent<EventTarget>) => {\n    //         //     console.log(\"Progress[END!]:\", ev.loaded, ev.total, Math.ceil(ev.loaded / ev.total * 10000 / 100))\n    //         //     resolve()\n    //         //     // onprogress(100, true)\n    //         // }\n    //         // req.open(\"POST\", '/resumable');\n    //         // req.send(formData);\n    //         const request = new Request('/resumable', {\n    //             method: 'POST',\n    //             body: formData,\n    //         });\n    //         fetch(request).then(async (response) => {\n    //             console.log(await response.text())\n    //         })\n    //         resolve()\n    //     })\n    //     console.log(\"SEND CHUNK wait:\", x.hash)\n    //     await p;\n    //     console.log(\"SEND CHUNK done:\", x.hash)\n    // }\n    // const res = new Resumable({\n    //     target: '/resumable',\n    //     // chunkSize: 100 * 1024,\n    //     simultaneousUploads: 1,\n    // })\n    // res.on(\"progress\", () => {\n    //     console.log(\"PROGRESS:\", res.progress)\n    // })\n    // res.on(\"uploadStart\", () => {\n    //     console.log(\"uploadStart:\")\n    // })\n    // res.on(\"fileSuccess\", (file: Resumable.ResumableFile) => {\n    //     console.log(\"fileSuccess:\", file)\n    // })\n    // res.on(\"fileAdded\", () => {\n    //     console.log(\"fileAdded:\")\n    // })\n    // res.on(\"fileError\", () => {\n    //     console.log(\"fileError:\")\n    // })\n    // res.addFile(modelFile)\n    // res.addFile(_configFile)\n    // console.log(\"send\", res.files, res.getSize())\n    // res.upload()\n};\n\n\n//# sourceURL=webpack://voice-changer-internal/./frontend/src/001_clients_and_managers/002_ResourceLoader.ts?");
+eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"fetchTextResource\": () => (/* binding */ fetchTextResource),\n/* harmony export */   \"postVoice\": () => (/* binding */ postVoice),\n/* harmony export */   \"uploadModelProps\": () => (/* binding */ uploadModelProps),\n/* harmony export */   \"uploadModelPropsResumable\": () => (/* binding */ uploadModelPropsResumable)\n/* harmony export */ });\n/* provided dependency */ var Buffer = __webpack_require__(/*! buffer */ \"./node_modules/buffer/index.js\")[\"Buffer\"];\n// import Resumable from 'resumablejs'\n// import { file } from \"jszip\";\nconst fetchTextResource = async (url) => {\n    const res = await fetch(url, {\n        method: \"GET\"\n    });\n    const text = res.text();\n    return text;\n};\nconst postVoice = async (url, gpu, srcId, dstId, timestamp, buffer) => {\n    const obj = {\n        gpu, srcId, dstId, timestamp, buffer: Buffer.from(buffer).toString('base64')\n    };\n    const body = JSON.stringify(obj);\n    const res = await fetch(`${url}`, {\n        method: \"POST\",\n        headers: {\n            'Accept': 'application/json',\n            'Content-Type': 'application/json'\n        },\n        body: body\n    });\n    const receivedJson = await res.json();\n    const changedVoiceBase64 = receivedJson[\"changedVoiceBase64\"];\n    const buf = Buffer.from(changedVoiceBase64, \"base64\");\n    const ab = new ArrayBuffer(buf.length);\n    // console.log(\"RECIV\", buf.length)\n    const view = new Uint8Array(ab);\n    for (let i = 0; i < buf.length; ++i) {\n        view[i] = buf[i];\n    }\n    return ab;\n};\nconst uploadModelProps = (modelFile, configFile, onprogress) => {\n    const req = new XMLHttpRequest();\n    const formData = new FormData();\n    formData.append(\"modelFile\", modelFile);\n    formData.append(\"configFile\", configFile);\n    req.upload.onprogress = (ev) => {\n        const progress = Math.ceil(ev.loaded / ev.total * 10000 / 100);\n        console.log(\"Progress:\", ev.loaded, ev.total, progress);\n        onprogress(progress, ev.loaded == ev.total);\n    };\n    req.upload.onloadend = (ev) => {\n        console.log(\"Progress[END!]:\", ev.loaded, ev.total, Math.ceil(ev.loaded / ev.total * 10000 / 100));\n        onprogress(100, true);\n    };\n    req.open(\"POST\", '/upload_model_file');\n    req.send(formData);\n};\nconst uploadModelPropsResumable = async (modelFile, configFile, _onprogress) => {\n    const size = 1024 * 1024;\n    // const size = modelFile.size / 10;\n    const fileChunks = [];\n    let index = 0; // index値\n    for (let cur = 0; cur < modelFile.size; cur += size) {\n        fileChunks.push({\n            hash: index++,\n            chunk: modelFile.slice(cur, cur + size),\n        });\n    }\n    const chunkNum = fileChunks.length;\n    console.log(\"FILE_CHUNKS:\", chunkNum, fileChunks);\n    while (true) {\n        const promises = [];\n        for (let i = 0; i < 10; i++) {\n            const chunk = fileChunks.shift();\n            if (!chunk) {\n                break;\n            }\n            const p = new Promise((resolve) => {\n                const formData = new FormData();\n                formData.append(\"file\", chunk.chunk);\n                formData.append(\"filename\", `${modelFile.name}_${chunk.hash}`);\n                const request = new Request('/upload_file', {\n                    method: 'POST',\n                    body: formData,\n                });\n                fetch(request).then(async (response) => {\n                    console.log(await response.text());\n                    resolve();\n                });\n            });\n            promises.push(p);\n        }\n        await Promise.all(promises);\n        if (fileChunks.length == 0) {\n            break;\n        }\n    }\n    console.log(\"model uploaded\");\n    const configP = new Promise((resolve) => {\n        const formData = new FormData();\n        formData.append(\"file\", configFile);\n        formData.append(\"filename\", configFile.name);\n        const request = new Request('/upload_file', {\n            method: 'POST',\n            body: formData,\n        });\n        fetch(request).then(async (response) => {\n            console.log(await response.text());\n            resolve();\n        });\n    });\n    await configP;\n    console.log(\"config uploaded\");\n    const loadP = new Promise((resolve) => {\n        const formData = new FormData();\n        formData.append(\"modelFilename\", modelFile.name);\n        formData.append(\"modelFilenameChunkNum\", \"\" + chunkNum);\n        formData.append(\"configFilename\", configFile.name);\n        const request = new Request('/load_model', {\n            method: 'POST',\n            body: formData,\n        });\n        fetch(request).then(async (response) => {\n            console.log(await response.text());\n            resolve();\n        });\n    });\n    await loadP;\n    console.log(\"model loaded\");\n    // for (const x of fileChunks) {\n    //     console.log(\"SEND CHUNK:\", x.hash)\n    //     const p = new Promise<void>((resolve, _reject) => {\n    //         // const req = new XMLHttpRequest();\n    //         const formData = new FormData();\n    //         formData.append(\"file\", x.chunk);\n    //         formData.append(\"filename\", \"file_\" + x.hash);\n    //         // req.upload.onprogress = (ev: ProgressEvent<EventTarget>) => {\n    //         //     const progress = Math.ceil(ev.loaded / ev.total * 10000 / 100)\n    //         //     console.log(\"Progress:\", ev.loaded, ev.total, progress)\n    //         //     // onprogress(progress, ev.loaded == ev.total)\n    //         // }\n    //         // req.upload.onloadend = (ev: ProgressEvent<EventTarget>) => {\n    //         //     console.log(\"Progress[END!]:\", ev.loaded, ev.total, Math.ceil(ev.loaded / ev.total * 10000 / 100))\n    //         //     resolve()\n    //         //     // onprogress(100, true)\n    //         // }\n    //         // req.open(\"POST\", '/resumable');\n    //         // req.send(formData);\n    //         const request = new Request('/resumable', {\n    //             method: 'POST',\n    //             body: formData,\n    //         });\n    //         fetch(request).then(async (response) => {\n    //             console.log(await response.text())\n    //         })\n    //         resolve()\n    //     })\n    //     console.log(\"SEND CHUNK wait:\", x.hash)\n    //     await p;\n    //     console.log(\"SEND CHUNK done:\", x.hash)\n    // }\n    // const res = new Resumable({\n    //     target: '/resumable',\n    //     // chunkSize: 100 * 1024,\n    //     simultaneousUploads: 1,\n    // })\n    // res.on(\"progress\", () => {\n    //     console.log(\"PROGRESS:\", res.progress)\n    // })\n    // res.on(\"uploadStart\", () => {\n    //     console.log(\"uploadStart:\")\n    // })\n    // res.on(\"fileSuccess\", (file: Resumable.ResumableFile) => {\n    //     console.log(\"fileSuccess:\", file)\n    // })\n    // res.on(\"fileAdded\", () => {\n    //     console.log(\"fileAdded:\")\n    // })\n    // res.on(\"fileError\", () => {\n    //     console.log(\"fileError:\")\n    // })\n    // res.addFile(modelFile)\n    // res.addFile(_configFile)\n    // console.log(\"send\", res.files, res.getSize())\n    // res.upload()\n};\n\n\n//# sourceURL=webpack://voice-changer-internal/./frontend/src/001_clients_and_managers/002_ResourceLoader.ts?");
 
 /***/ }),
 
diff --git a/trainer/Dockerfile b/trainer/Dockerfile
index d1940f8b..d0769f55 100644
--- a/trainer/Dockerfile
+++ b/trainer/Dockerfile
@@ -1,4 +1,4 @@
-FROM dannadori/voice-changer-internal:20221030_212136 as front
+FROM dannadori/voice-changer-internal:20221030_223546 as front
 FROM debian:bullseye-slim as base
 
 ARG DEBIAN_FRONTEND=noninteractive