john 7 месяцев назад
Родитель
Сommit
1ed7968023

+ 16 - 0
epub_node/README.md

@@ -1,21 +1,37 @@
 # DB
+
 地址: localhost:3306
 账号密码:root:12345678
 
 # dockerfile
 
 创建镜像
+
 ```
 docker build -t hht/epub2:v1 .
 ```
 
 打包
+
 ```bash
 docker save -o ./epub.tar hht/epub2:v1
 ```
 
 启动
+
 ```bash
 docker run -p 3000:3000 -v /f/code/newCashBook/epub_node:/app hht/epub2:v1
 ```
 
+清理数据库
+
+```bash
+DELETE FROM epub_manage.book;
+DELETE FROM epub_manage.author;
+DELETE FROM epub_manage.category;
+DELETE FROM epub_manage.style;
+DELETE FROM epub_manage.style_link_book;
+DELETE FROM epub_manage.chapter;
+DELETE FROM epub_manage.files;
+DELETE FROM epub_manage.book_link_file;
+```

+ 7 - 0
epub_node/db/update.sql

@@ -102,3 +102,10 @@ create table style_link_book
     constraint fk_style foreign key (style_id) references style (style_id) on delete cascade
 );
 
+
+
+ALTER TABLE epub_manage.chapter ADD level INT NULL;
+ALTER TABLE epub_manage.chapter ADD order_index INT NULL;
+ALTER TABLE epub_manage.chapter ADD order_id VARCHAR(255) NULL;
+ALTER TABLE epub_manage.chapter ADD old_path VARCHAR(255) NULL;
+ALTER TABLE epub_manage.chapter ADD path VARCHAR(255) NULL;

+ 7 - 7
epub_node/environment/index.js

@@ -1,12 +1,12 @@
 function dbInfo() {
   // 根据需要更新db的数据配置
-  return {
-    host: "localhost",
-    port: 3306,
-    user: "root",
-    password: "12345678",
-    database: "epub_manage",
-  };
+  // return {
+  //   host: "localhost",
+  //   port: 3306,
+  //   user: "root",
+  //   password: "12345678",
+  //   database: "epub_manage",
+  // };
   return {
     host: "192.168.2.101",
     port: 6806,

+ 1 - 0
epub_node/package.json

@@ -27,6 +27,7 @@
     "adm-zip": "^0.5.16",
     "body-parser": "^1.20.3",
     "cheerio": "^1.0.0",
+    "cli-progress": "^3.12.0",
     "cors": "^2.8.5",
     "crypto": "^1.0.1",
     "dayjs": "^1.11.13",

+ 47 - 41
epub_node/router/epub/font.js

@@ -3,76 +3,82 @@ import { files_insert, files_insert_link_epub } from "#db";
 import { dirExists } from "#utils";
 import fs from "node:fs";
 import { calculateMD5 } from "./image.js";
+import cliProgress from 'cli-progress';
 
-// ./base_files/5ae2d9158081faab184484ed1783e176
 export async function saveAllFount(epub, uploadPath, book_id, author_id) {
   dirExists(uploadPath);
   dirExists(`${uploadPath}font/`);
 
   // 获取原始数据源
-  const getAllCss = epub.zip.names.filter((elm) => elm.indexOf("ttf") > -1);
+  const getAllCss = epub.zip.names.filter((elm) => elm.includes("ttf"));
   const base_path = `${uploadPath}epub-extract/`;
+
   if (getAllCss.length) {
     const cssRes = await Promise.allSettled(
       getAllCss.map((img) => {
-        return fs.readFileSync(base_path + img, "utf8");
+        return fs.promises.readFile(base_path + img, "utf8");
       })
     );
+
     const allCss_fulfilled = cssRes
-      .map((img, index) => {
-        const img_fulfilled = cssRes[index];
+      .map((img_fulfilled, index) => {
         const cssPath = getAllCss[index];
         if (img_fulfilled.status === "fulfilled") {
-          // const file_md5 = await calculateMD5(base_path + cssPath)
           return {
-            ...img,
-            ...img_fulfilled,
             index,
             path: base_path + cssPath,
-            cssPath, // md5: file_md5,
+            cssPath,
             css_data: img_fulfilled.value,
             mimeType: "font/ttf",
           };
         }
-        return false;
+        return null;
       })
-      .filter((elm) => elm);
+      .filter(Boolean);
+
+    // Initialize the progress bar
+    const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);
+    progressBar.start(allCss_fulfilled.length, 0);
 
     await Promise.allSettled(
-      allCss_fulfilled.map(async (elm) => {
-        const md5 = await calculateMD5(elm.path);
-        const [elmPath, elmName] = `${elm.path}`.match(/.*\/(.*\.ttf)/);
+      allCss_fulfilled.map(async (elm, index) => {
+        try {
+          const md5 = await calculateMD5(elm.path);
+          const elmName = elm.cssPath.split('/').pop();
+
+          // Write the font data to a file
+          await fs.promises.writeFile(`${uploadPath}font/${md5}.ttf`, elm.css_data);
+          logger.info("Font data saved to " + md5);
 
-        //
-        // 移动文件
-        // './base_files/5ae2d9158081faab184484ed1783e176/epub-extract/OEBPS/flow0001.css'
-        // ./base_files/5ae2d9158081faab184484ed1783e176/style/flow0001.css
-        //
+          const params = {
+            file_id: md5,
+            md5: md5,
+            mimetype: elm.mimeType,
+            size: elm.css_data.length,
+            name: elmName,
+            path: `${uploadPath}font/${md5}.ttf`,
+            source_id: md5,
+          };
 
-        fs.writeFile(`${uploadPath}font/${md5}.ttf`, elm.css_data, (err) => {
-          if (err) {
-            logger.error("Error writing Img file:", err);
-          } else {
-            logger.info("Img data saved to " + md5);
-          }
-        });
+          await files_insert(params);
+          await files_insert_link_epub({
+            file_id: md5,
+            book_id,
+            author_id,
+          });
 
-        const params = {
-          file_id: md5,
-          md5: md5,
-          mimetype: elm.mimeType,
-          size: elm.css_data.length,
-          name: elmName,
-          path: `${uploadPath}font/${md5}.ttf`,
-          source_id: md5,
-        };
-        await files_insert(params);
-        return await files_insert_link_epub({
-          file_id: md5,
-          book_id,
-          author_id,
-        });
+          // Update the progress bar
+          progressBar.update(index + 1);
+        } catch (err) {
+          logger.error("Error processing font:", err);
+        }
       })
     );
+
+    // Update the progress bar
+    progressBar.update(allCss_fulfilled.length);
+
+    // Stop the progress bar
+    progressBar.stop();
   }
 }

+ 54 - 47
epub_node/router/epub/image.js

@@ -3,63 +3,70 @@ import { files_insert, files_insert_link_epub } from "#db";
 import crypto from "crypto";
 import fs from "node:fs";
 import logger from "#logger";
+import cliProgress from 'cli-progress';
 
 export async function saveImgs(epub, uploadPath, book_id, author_id) {
   dirExists(uploadPath + "image/");
-  let imgs = epub.listImage();
+  const imgs = epub.listImage();
+
   if (imgs.length) {
     const imgRes = await Promise.allSettled(
-      imgs.map((img) => {
-        return epub.getImageAsync(img.id);
-      })
+      imgs.map((img) => epub.getImageAsync(img.id))
     );
-    // 过滤数据
-
-    const imgs_fulfilled = imgs
-      .map((img, index) => {
-        const img_fulfilled = imgRes[index];
-        if (img_fulfilled.status === "fulfilled") {
-          const [img_data, img_mimeType] = img_fulfilled.value;
-          return {
-            ...img,
-            index,
-            img_data,
-            img_mimeType,
-          };
-        }
-        return false;
-      })
-      .filter((elm) => elm);
+    const imgs_fulfilled = imgs.map((img, index) => {
+      const img_fulfilled = imgRes[index];
+      if (img_fulfilled.status === "fulfilled") {
+        const [img_data, img_mimeType] = img_fulfilled.value;
+        return {
+          ...img,
+          img_data,
+          img_mimeType,
+        };
+      }
+      return null;
+    }).filter(Boolean);
+
+    // Initialize the progress bar
+    const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);
+    progressBar.start(imgs_fulfilled.length, 0);
 
     await Promise.allSettled(
-      imgs_fulfilled.map(async (elm) => {
-        const img_md5 = await calculateMD5FromBuffer(elm.img_data);
-
-        const imgUploadPath = uploadPath + "image/" + img_md5;
-        const params = {
-          file_id: img_md5,
-          md5: img_md5,
-          mimetype: elm.img_mimeType,
-          size: elm.img_data.length,
-          name: elm.id,
-          path: elm.href,
-          source_id: elm.id,
-        };
-        fs.writeFile(imgUploadPath, elm.img_data, (err) => {
-          if (err) {
-            logger.error("Error writing Img file:", err);
-          } else {
-            logger.info("Img data saved to " + img_md5);
-          }
-        });
-        await files_insert(params);
-        return await files_insert_link_epub({
-          file_id: img_md5,
-          book_id,
-          author_id,
-        });
+      imgs_fulfilled.map(async (elm, index) => {
+        try {
+          const img_md5 = await calculateMD5FromBuffer(elm.img_data);
+          const imgUploadPath = `${uploadPath}image/${img_md5}`;
+          const params = {
+            file_id: img_md5,
+            md5: img_md5,
+            mimetype: elm.img_mimeType,
+            size: elm.img_data.length,
+            name: elm.id,
+            path: elm.href,
+            source_id: elm.id,
+          };
+
+          await fs.promises.writeFile(imgUploadPath, elm.img_data);
+          logger.info("Img data saved to " + img_md5);
+
+          await files_insert(params);
+          await files_insert_link_epub({
+            file_id: img_md5,
+            book_id,
+            author_id,
+          });
+
+          // Update the progress bar
+          progressBar.update(index + 1);
+        } catch (err) {
+          logger.error("Error processing image:", err);
+        }
       })
     );
+
+    // Update the progress bar
+    progressBar.update(imgs_fulfilled.length);
+    // Stop the progress bar
+    progressBar.stop();
   }
 }
 

+ 1 - 1
epub_node/router/epub/index.js

@@ -162,6 +162,7 @@ router.put("/", async function (req, res) {
       4、存储css数据
       5、存储章节数据
      */
+    res.send("书籍正在处理中,请稍后!");
     await saveMateInfo(epub, uploadPath, file_md5, author_id)
     logger.info('书籍的基础数据处理完毕')
     await saveImgs(epub, uploadPath, file_md5, author_id);
@@ -177,7 +178,6 @@ router.put("/", async function (req, res) {
     await saveToc(epub, zipEpubExtract, file_md5, author_id);
     logger.info('书籍的目录处理完毕')
     logger.info('书籍处理完毕')
-    res.send("书籍处理完毕");
 });
 
 export default router;

+ 94 - 83
epub_node/router/epub/style.js

@@ -1,88 +1,99 @@
 import logger from "#logger";
-import {files_insert, files_insert_link_epub} from "#db";
-import {dirExists} from "#utils";
+import { files_insert, files_insert_link_epub } from "#db";
+import { dirExists } from "#utils";
 import fs from "node:fs";
-import {calculateMD5} from "./image.js";
+import { calculateMD5 } from "./image.js";
+import cliProgress from "cli-progress";
 
-// ./base_files/5ae2d9158081faab184484ed1783e176
 export async function saveAllCSS(epub, uploadPath, book_id, author_id) {
-    dirExists(uploadPath);
-    dirExists(`${uploadPath}style/`);
-    
-    // 获取原始数据源
-    const getAllCss = epub.zip.names.filter((elm) => elm.indexOf("css") > -1);
-    const base_path = `${uploadPath}epub-extract/`;
-    if (getAllCss.length) {
-        const cssRes = await Promise.allSettled(
-            getAllCss.map((img) => {
-                return fs.readFileSync(base_path + img, "utf8");
-            })
-        );
-        const allCss_fulfilled = cssRes
-            .map((img, index) => {
-                const img_fulfilled = cssRes[index];
-                const cssPath = getAllCss[index];
-                if (img_fulfilled.status === "fulfilled") {
-                    // const file_md5 = await calculateMD5(base_path + cssPath)
-                    return {
-                        ...img,
-                        ...img_fulfilled,
-                        index,
-                        path: base_path + cssPath,
-                        cssPath, // md5: file_md5,
-                        css_data: img_fulfilled.value,
-                        mimeType: "text/css",
-                    };
-                }
-                return false;
-            })
-            .filter((elm) => elm);
-        
-        await Promise.allSettled(
-            allCss_fulfilled.map(async (elm) => {
-                const md5 = await calculateMD5(elm.path);
-                let file_path;
-                let source_id;
-                const [elmPath, elmName] = `${elm.path}`.match(/.*\/(.*\.css)/);
-                
-                //
-                // 移动文件
-                // './base_files/5ae2d9158081faab184484ed1783e176/epub-extract/OEBPS/flow0001.css'
-                // ./base_files/5ae2d9158081faab184484ed1783e176/style/flow0001.css
-                //
-                
-                fs.writeFile(`${uploadPath}style/${md5}.css`, elm.css_data, (err) => {
-                    if (err) {
-                        logger.error("Error writing Img file:", err);
-                    } else {
-                        logger.info("Img data saved to " + md5);
-                    }
-                });
-                Object.keys(epub.manifest).forEach(m_key => {
-                    const mElm = epub.manifest[m_key];
-                    if (mElm.href.indexOf(elmName) > -1 && !source_id) {
-                        source_id = mElm.id;
-                        file_path = mElm.href
-                    }
-                })
-                
-                const params = {
-                    file_id: md5,
-                    md5: md5,
-                    mimetype: elm.mimeType,
-                    size: elm.css_data.length,
-                    name: elmName,
-                    // path: `${uploadPath}style/${md5}.css`,
-                    path: file_path,
-                    source_id: source_id,
-                };
-                await files_insert(params);
-                return await files_insert_link_epub({
-                    file_id: md5,
-                    book_id,
-                    author_id,
-                });
-            })
-        );
-    }
+  dirExists(uploadPath);
+  dirExists(`${uploadPath}style/`);
+
+  // 获取原始数据源
+  const getAllCss = epub.zip.names.filter((elm) => elm.includes("css"));
+  const base_path = `${uploadPath}epub-extract/`;
+
+  if (getAllCss.length) {
+    const cssRes = await Promise.allSettled(
+      getAllCss.map((css) => fs.promises.readFile(base_path + css, "utf8"))
+    );
+
+    const allCss_fulfilled = cssRes
+      .map((css_fulfilled, index) => {
+        const cssPath = getAllCss[index];
+        if (css_fulfilled.status === "fulfilled") {
+          return {
+            index,
+            path: base_path + cssPath,
+            cssPath,
+            css_data: css_fulfilled.value,
+            mimeType: "text/css",
+          };
+        }
+        return null;
+      })
+      .filter(Boolean);
+
+    // Initialize the progress bar
+    const progressBar = new cliProgress.SingleBar(
+      {},
+      cliProgress.Presets.shades_classic
+    );
+    progressBar.start(allCss_fulfilled.length, 0);
+
+    await Promise.allSettled(
+      allCss_fulfilled.map(async (elm, index) => {
+        try {
+          const md5 = await calculateMD5(elm.path);
+          const elmName = elm.cssPath.split("/").pop();
+
+          // Write the CSS data to a file
+          await fs.promises.writeFile(
+            `${uploadPath}style/${md5}.css`,
+            elm.css_data
+          );
+          logger.info("CSS data saved to " + md5);
+
+          let file_path;
+          let source_id;
+          for (const m_key in epub.manifest) {
+            const mElm = epub.manifest[m_key];
+            if (mElm.href.includes(elmName) && !source_id) {
+              source_id = mElm.id;
+              file_path = mElm.href;
+              break;
+            }
+          }
+
+          const params = {
+            file_id: md5,
+            md5: md5,
+            mimetype: elm.mimeType,
+            size: elm.css_data.length,
+            name: elmName,
+            path: file_path,
+            source_id: source_id,
+          };
+
+          await files_insert(params);
+          await files_insert_link_epub({
+            file_id: md5,
+            book_id,
+            author_id,
+          });
+
+          // Update the progress bar
+          progressBar.update(index + 1);
+        } catch (err) {
+          logger.error("Error processing CSS:", err);
+        }
+      })
+    );
+
+    // Update the progress bar
+    progressBar.update(allCss_fulfilled.length);
+
+    // Stop the progress bar
+    progressBar.stop();
+  }
 }

+ 27 - 17
epub_node/router/epub/toc.js

@@ -1,23 +1,26 @@
 import logger from "#logger";
-import {chapter_insert, searchChapterInfoForPath} from "#db";
-import {dirExists} from "#utils";
+import { chapter_insert, searchChapterInfoForPath } from "#db";
+import { dirExists } from "#utils";
 import fs from "node:fs";
-import {calculateMD5} from "./image.js";
+import { calculateMD5 } from "./image.js";
+import cliProgress from 'cli-progress';
 
-// ./base_files/5ae2d9158081faab184484ed1783e176
 export async function saveToc(epub, uploadPath, book_id, author_id) {
-    await Promise.all(epub.toc.map(async (elm) => {
+    // 初始化进度条
+    const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);
+    progressBar.start(epub.toc.length, 0);
+
+    await Promise.allSettled(epub.toc.map(async (elm, index) => {
         try {
-            const match = `${elm.href}`.match(/\/(.*\.html).*/)
-            let chapterInfo = {
-                file_id: ''
-            }
-            let path = ''
+            const match = elm.href.match(/\/(.*\.html).*/);
+            let chapterInfo = { file_id: '' };
+            let path = '';
+
             if (match) {
                 path = match[1];
-                chapterInfo = await searchChapterInfoForPath(path, book_id)
+                chapterInfo = await searchChapterInfoForPath(path, book_id);
             }
-            logger.info(elm)
+
             const params = {
                 name: elm.title,
                 book_id: book_id,
@@ -28,11 +31,18 @@ export async function saveToc(epub, uploadPath, book_id, author_id) {
                 order_id: chapterInfo.file_id,
                 old_path: elm.href,
                 path: `./base_files/${book_id}/Text/${chapterInfo.file_id}.html`,
-            }
-            logger.info(params)
-            return await chapter_insert(params)
+            };
+            // 更新进度条
+            progressBar.update(index + 1);
+            await chapter_insert(params);
         } catch (e) {
-            logger.error(e)
+            logger.error(e);
         }
-    }))
+    }));
+
+    // 更新进度条
+    progressBar.update(epub.toc.length);
+
+    // 停止进度条
+    progressBar.stop();
 }

+ 139 - 144
epub_node/router/epub/txt.js

@@ -1,161 +1,156 @@
 import fs from "node:fs";
 import path from "node:path";
-import {dirExists, isFileSync, isDir, waittime} from "#utils";
+import { dirExists, isFileSync, isDir, waittime } from "#utils";
 import {
-    getFileBymd5,
-    searchFileByPath,
-    searchFileByName,
-    files_insert_link_epub,
-    files_insert,
-    book_mate_insert,
+  getFileBymd5,
+  searchFileByPath,
+  searchFileByName,
+  files_insert_link_epub,
+  files_insert,
+  book_mate_insert,
 } from "#db";
-import {calculateMD5} from "./image.js";
+import { calculateMD5 } from "./image.js";
+import cliProgress from "cli-progress";
+import logger from "#logger";
 
 const imageExtensions = [".png", ".jpg", ".jpeg", ".svg"];
 
 async function processFiles(elmData, file_md5) {
-    const rows = elmData.toString().split(/\n/);
-    const promises = rows.map(async (rowtext) => {
-        if (
-            rowtext.includes("<img ") &&
-            imageExtensions.some((ext) => rowtext.includes(ext))
-        ) {
-            // const match = rowtext.match(/.*(..\/Images\/(.*\.(jpg|png|jpeg|svg))).*/);
-            const match = rowtext.match(/src=("|')(.*\/(.*\.[a-zA-Z]+))("|')/)
-            if (match) {
-                const [, , imgPath, imageSrc] = match;
-                const imgRow = await searchFileByPath(imageSrc);
-                if (imgRow) {
-                    return (
-                        rowtext.replace(imgPath, `/api/v1/epub/img/${imgRow.file_id}`) +
-                        "\n"
-                    );
-                }
-            }
-        } else if (rowtext.includes(".css")) {
-            const match = rowtext.match(/.*="(.*\/?(.*\.css))/);
-            const [elmPath, elmName] = `${rowtext}`.match(/.*\/(.*\.css)/);
-            if (match) {
-                const [, cssPath, cssSrc] = match;
-                // const imgRow = await searchFileByPath(elmName, file_md5);
-                const imgNameRow =  await searchFileByName(elmName, file_md5);
-                if (imgNameRow) {
-                    return (
-                        rowtext.replace(cssPath, `/api/v1/epub/css/${imgNameRow.file_id}`) +
-                        "\n"
-                    );
-                }
-            }
-        } else if (rowtext.includes(".ttf")) {
-            // 使用正则表达式匹配路径和文件名
-            const match = rowtext.match(/.*\((.*\/?(.*ttf))\)./);
-            if (match) {
-                const [, cssPath, cssSrc] = match;
-                try {
-                    // 搜索数据库中是否存在该字体文件
-                    const imgRow = await searchFileByPath(cssSrc, file_md5);
-                    if (imgRow) {
-                        // 如果找到,替换路径为 API 端点
-                        console.log(57, rowtext);
-                        console.log(58, cssPath, cssSrc);
-                        console.log(59, `/api/v1/epub/css/${imgRow.file_id}`);
-                        
-                        return (
-                            rowtext.replace(cssPath, `/api/v1/epub/css/${imgRow.file_id}`) +
-                            "\n"
-                        );
-                    } else {
-                        console.warn(`Font file not found for path: ${cssSrc}`);
-                    }
-                } catch (error) {
-                    console.error("Error searching for font file:", error);
-                }
-            }
+  const rows = elmData.toString().split(/\n/);
+  const promises = rows.map(async (rowtext) => {
+    if (
+      rowtext.includes("<img ") &&
+      imageExtensions.some((ext) => rowtext.includes(ext))
+    ) {
+      const match = rowtext.match(/src=("|')(.*\/(.*\.[a-zA-Z]+))("|')/);
+      if (match) {
+        const [, , imgPath, imageSrc] = match;
+        const imgRow = await searchFileByPath(imageSrc);
+        if (imgRow) {
+          return (
+            rowtext.replace(imgPath, `/api/v1/epub/img/${imgRow.file_id}`) +
+            "\n"
+          );
         }
-        
-        return rowtext + "\n";
-    });
-    
-    const results = await Promise.all(promises);
-    return results.join("");
+      }
+    } else if (rowtext.includes(".css")) {
+      const match = rowtext.match(/.*="(.*\/?(.*\.css))/);
+      const [elmPath, elmName] = `${rowtext}`.match(/.*\/(.*\.css)/);
+      if (match) {
+        const [, cssPath, cssSrc] = match;
+        const imgNameRow = await searchFileByName(elmName, file_md5);
+        if (imgNameRow) {
+          return (
+            rowtext.replace(cssPath, `/api/v1/epub/css/${imgNameRow.file_id}`) +
+            "\n"
+          );
+        }
+      }
+    } else if (rowtext.includes(".ttf")) {
+      const match = rowtext.match(/.*\((.*\/?(.*ttf))\)./);
+      if (match) {
+        const [, cssPath, cssSrc] = match;
+        try {
+          const imgRow = await searchFileByPath(cssSrc, file_md5);
+          if (imgRow) {
+            return (
+              rowtext.replace(cssPath, `/api/v1/epub/css/${imgRow.file_id}`) +
+              "\n"
+            );
+          } else {
+            logger.warn(`Font file not found for path: ${cssSrc}`);
+          }
+        } catch (error) {
+            logger.error("Error searching for font file:", error);
+        }
+      }
+    }
+    return rowtext + "\n";
+  });
+
+  const results = await Promise.all(promises);
+  return results.join("");
 }
 
 export async function htmlParser(epub, zipEpubExtract, file_md5, author_id) {
-    const needSetImage = epub.zip.names.filter(
-        (elm) => elm.endsWith(".html") || elm.endsWith(".css")
-    );
-    
-    const needSetFont = epub.zip.names.filter((elm) => elm.endsWith(".ttf"));
-    const basePath = path.join("./base_files", file_md5, "Text");
-    const styleBasePath = path.join("./base_files", file_md5, "style");
-    dirExists(basePath);
-    dirExists(styleBasePath);
-    
-    await Promise.all(
-        needSetImage.map(async (elm) => {
-            const filePath = path.join(zipEpubExtract, elm);
-            const elmData = fs.readFileSync(filePath);
-            const htmlStr = await processFiles(elmData, file_md5);
-            let file_path;
-            let source_id;
-            
-            if (htmlStr) {
-                fs.writeFileSync(filePath, htmlStr);
-                
-                const htmlMd5 = await calculateMD5(filePath);
-                const isCss = elm.endsWith(".css");
-                const newFilePath = path.join(
-                    isCss ? styleBasePath : basePath,
-                    `${htmlMd5}.${isCss ? "css" : "html"}`
-                );
-                
-                Object.keys(epub.manifest).forEach(m_key => {
-                    const mElm = epub.manifest[m_key];
-                    if (mElm.href.indexOf(elm) > -1 && !source_id) {
-                        source_id = mElm.id;
-                        file_path = mElm.href
-                    }
-                })
-                
-                const params = {
-                    file_id: htmlMd5,
-                    md5: htmlMd5,
-                    mimetype: isCss ? "text/css" : "text/html",
-                    size: Buffer.byteLength(htmlStr),
-                    name: `${htmlMd5}.${isCss ? "css" : "html"}`,
-                    path: file_path,
-                    source_id: source_id,
-                };
-                await files_insert(params);
-                await Promise.all([
-                    files_insert_link_epub({
-                        file_id: htmlMd5,
-                        book_id: file_md5,
-                        author_id,
-                    }),
-                    fs.promises.writeFile(newFilePath, htmlStr),
-                ]);
-            }
-        })
-    );
+  const needSetImage = epub.zip.names.filter(
+    (elm) => elm.endsWith(".html") || elm.endsWith(".css")
+  );
+
+  const needSetFont = epub.zip.names.filter((elm) => elm.endsWith(".ttf"));
+  const basePath = path.join("./base_files", file_md5, "Text");
+  const styleBasePath = path.join("./base_files", file_md5, "style");
+  dirExists(basePath);
+  dirExists(styleBasePath);
+
+  // 初始化进度条
+  const progressBar = new cliProgress.SingleBar(
+    {},
+    cliProgress.Presets.shades_classic
+  );
+  progressBar.start(needSetImage.length, 0);
+
+  await Promise.allSettled(
+    needSetImage.map(async (elm, index) => {
+      const filePath = path.join(zipEpubExtract, elm);
+      const elmData = fs.readFileSync(filePath);
+      const htmlStr = await processFiles(elmData, file_md5);
+      let file_path;
+      let source_id;
+      if (htmlStr) {
+        fs.writeFileSync(filePath, htmlStr);
+
+        const htmlMd5 = await calculateMD5(filePath);
+        const isCss = elm.endsWith(".css");
+        const newFilePath = path.join(
+          isCss ? styleBasePath : basePath,
+          `${htmlMd5}.${isCss ? "css" : "html"}`
+        );
+
+        for (const m_key in epub.manifest) {
+          const mElm = epub.manifest[m_key];
+          if (mElm.href.includes(elm) && !source_id) {
+            source_id = mElm.id;
+            file_path = mElm.href;
+            break;
+          }
+        }
+
+        const params = {
+          file_id: htmlMd5,
+          md5: htmlMd5,
+          mimetype: isCss ? "text/css" : "text/html",
+          size: Buffer.byteLength(htmlStr),
+          name: `${htmlMd5}.${isCss ? "css" : "html"}`,
+          path: file_path,
+          source_id: source_id,
+        };
+        await files_insert(params);
+        await Promise.allSettled([
+          files_insert_link_epub({
+            file_id: htmlMd5,
+            book_id: file_md5,
+            author_id,
+          }),
+          fs.promises.writeFile(newFilePath, htmlStr),
+          progressBar.update(index + 1)
+        ]);
+      }
+    })
+  );
+
+  // 停止进度条
+  progressBar.stop();
 }
 
 // saveMateInfo
 export async function saveMateInfo(epub, zipEpubExtract, file_md5, author_id) {
-    // book_mate_insert
-    const params = {
-        book_name: epub.metadata.title,
-        book_id: file_md5,
-        book_md5: file_md5,
-        // language: "",
-        // date: "",
-        // creatorFileAs: "",
-        // UUID: "",
-        // ISBN: "",
-        author_id: author_id,
-        // category_id: "",
-        // Introduction: "",
-    };
-    
-    const res = await book_mate_insert(params);
+  const params = {
+    book_name: epub.metadata.title,
+    book_id: file_md5,
+    book_md5: file_md5,
+    author_id: author_id,
+  };
+
+  await book_mate_insert(params);
 }

+ 38 - 0
epub_node/yarn.lock

@@ -142,6 +142,11 @@ adm-zip@^0.5.10, adm-zip@^0.5.16:
   resolved "https://registry.npmmirror.com/adm-zip/-/adm-zip-0.5.16.tgz#0b5e4c779f07dedea5805cdccb1147071d94a909"
   integrity sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==
 
+ansi-regex@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
+  integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
+
 anymatch@~3.1.2:
   version "3.1.3"
   resolved "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
@@ -303,6 +308,13 @@ chokidar@^3.5.2:
   optionalDependencies:
     fsevents "~2.3.2"
 
+cli-progress@^3.12.0:
+  version "3.12.0"
+  resolved "https://registry.npmmirror.com/cli-progress/-/cli-progress-3.12.0.tgz#807ee14b66bcc086258e444ad0f19e7d42577942"
+  integrity sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==
+  dependencies:
+    string-width "^4.2.3"
+
 color-convert@^1.9.3:
   version "1.9.3"
   resolved "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
@@ -504,6 +516,11 @@ ee-first@1.1.1:
   resolved "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
   integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
 
+emoji-regex@^8.0.0:
+  version "8.0.0"
+  resolved "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
+  integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
+
 enabled@2.0.x:
   version "2.0.0"
   resolved "https://registry.npmmirror.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2"
@@ -793,6 +810,11 @@ is-extglob@^2.1.1:
   resolved "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
   integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
 
+is-fullwidth-code-point@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
+  integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
+
 is-glob@^4.0.1, is-glob@~4.0.1:
   version "4.0.3"
   resolved "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
@@ -1304,6 +1326,15 @@ streamsearch@^1.1.0:
   resolved "https://registry.npmmirror.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764"
   integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
 
+string-width@^4.2.3:
+  version "4.2.3"
+  resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+  integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+  dependencies:
+    emoji-regex "^8.0.0"
+    is-fullwidth-code-point "^3.0.0"
+    strip-ansi "^6.0.1"
+
 string_decoder@^1.1.1:
   version "1.3.0"
   resolved "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
@@ -1318,6 +1349,13 @@ string_decoder@~1.1.1:
   dependencies:
     safe-buffer "~5.1.0"
 
+strip-ansi@^6.0.1:
+  version "6.0.1"
+  resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+  integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+  dependencies:
+    ansi-regex "^5.0.1"
+
 supports-color@^5.5.0:
   version "5.5.0"
   resolved "https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"