From b5441f941d91732caa7e33c7ab2dc531874c3efc Mon Sep 17 00:00:00 2001 From: Tianpao Date: Sat, 20 Sep 2025 22:42:12 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E6=94=B9=E4=BA=86=E4=B8=80?= =?UTF-8?q?=E5=A4=A7=E5=A0=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/Dex.ts | 69 ++++++++++++++ backend/src/core.ts | 60 ++++++++++++ backend/src/main.ts | 80 ++++------------ backend/src/modloader/fabric.ts | 0 backend/src/modloader/forge.ts | 94 ++++++++++++++++++ backend/src/modloader/index.ts | 15 +++ backend/src/modloader/minecraft.ts | 66 +++++++++++++ backend/src/modloader/neoforge.ts | 0 backend/src/platform/curseforge.ts | 3 + backend/src/platform/index.ts | 24 +++-- backend/src/platform/mcbbs.ts | 20 ---- backend/src/utils/DeEarth.ts | 148 +++++++++++++++++++++++++++++ backend/src/utils/config.ts | 4 +- backend/src/utils/utils.ts | 83 +++++++++++++++- backend/src/utils/yauzl.promise.ts | 22 ++++- front/src/App.vue | 1 + front/src/component/Main.vue | 3 +- front/src/component/Setting.vue | 5 +- 18 files changed, 587 insertions(+), 110 deletions(-) create mode 100644 backend/src/Dex.ts create mode 100644 backend/src/core.ts create mode 100644 backend/src/modloader/fabric.ts create mode 100644 backend/src/modloader/forge.ts create mode 100644 backend/src/modloader/index.ts create mode 100644 backend/src/modloader/minecraft.ts create mode 100644 backend/src/modloader/neoforge.ts delete mode 100644 backend/src/platform/mcbbs.ts create mode 100644 backend/src/utils/DeEarth.ts diff --git a/backend/src/Dex.ts b/backend/src/Dex.ts new file mode 100644 index 0000000..9751b26 --- /dev/null +++ b/backend/src/Dex.ts @@ -0,0 +1,69 @@ +import fs from "node:fs"; +import websocket from "ws"; +import { yauzl_promise } from "./utils/yauzl.promise.js"; +import { pipeline } from "node:stream/promises"; +import { platform, what_platform } from "./platform/index.js"; + +interface Iinfo{ + name:string + buffer:Buffer +} + +export class Dex { + ws: websocket; + in: any; + constructor(ws: websocket) { + this.ws = ws; + this.in = {} + } + + public async Main(buffer: Buffer) { + const info = await this._getinfo(buffer) + const plat = what_platform(info) + const mpname = this.in.name + await Promise.all([ + this._unzip(buffer,mpname), + platform(plat).downloadfile(this.in,`./instance/${mpname}`) + ]) + //await this._unzip(buffer); + } + + private async _getinfo(buffer: Buffer){ + const important_name = ["manifest.json","modrinth.index.json"] + let contain:string = "" + const zip = await yauzl_promise(buffer); + zip.filter(e=>important_name.includes(e.fileName)).forEach(async e=>{ + this.in = JSON.parse((await e.ReadEntry).toString()) + contain = e.fileName + }) + return contain; + } + + private async _unzip(buffer: Buffer,instancename:string) { + /* 解压Zip */ + const zip = await yauzl_promise(buffer); + let index = 0; + for await (const entry of zip) { + const ew = entry.fileName.endsWith("/"); + if (ew) { + await fs.promises.mkdir(`./instance/${instancename}/${entry.fileName}`, { + recursive: true, + }); + } + if (!ew&&entry.fileName.startsWith("overrides/")) { + const dirPath = `./instance/${instancename}/${entry.fileName.substring( + 0, + entry.fileName.lastIndexOf("/") + )}`; + await fs.promises.mkdir(dirPath, { recursive: true }); + const stream = await entry.openReadStream; + const write = fs.createWriteStream(`./instance/${instancename}/${entry.fileName}`); + await pipeline(stream, write); + } + this.ws.send(JSON.stringify({ status: "unzip", result: { name: entry.fileName,total: zip.length, current:index } })); + index++ + } + /* 解压完成 */ + this.ws.send(JSON.stringify({ status: "changed", result: undefined })); + } +} diff --git a/backend/src/core.ts b/backend/src/core.ts new file mode 100644 index 0000000..a331331 --- /dev/null +++ b/backend/src/core.ts @@ -0,0 +1,60 @@ +import express, { Application } from "express"; +import multer from "multer"; +import cors from "cors" +import websocket, { WebSocketServer } from "ws" +import { createServer, Server } from "node:http"; +import fs from "node:fs" +import { pipeline } from "node:stream/promises"; +import { Config, IConfig } from "./utils/config.js"; +import { yauzl_promise } from "./utils/yauzl.promise.js"; +export class Core { + private config: IConfig; + private readonly app: Application; + private readonly server: Server; + public ws!: websocket; + private readonly upload: multer.Multer; + private task: {} = {}; + constructor(config: IConfig) { + this.config = config + this.app = express(); + this.upload = multer() + this.server = createServer(this.app); + new WebSocketServer({ server: this.server }).on("connection", (ws) => { + this.ws = ws; + }) + } + + async DeEarthX(buffer:Buffer){ + + } + + express() { + this.app.use(cors()); + this.app.use(express.json()); + this.app.post("/start", this.upload.single("file"), (req, res) => { + if (!req.file) { + return; + } + this.DeEarthX(req.file.buffer) + res.json({ + status:200, + message:"task is peding" + }) + }) + this.app.get('/config/get', (req, res) => { + res.json(this.config) + }) + + this.app.post('/config/post', (req, res) => { + Config.write_config(req.body) + res.json({ status: 200 }) + }) + } + + start() { + this.express() + this.server.listen(37019, () => { + console.log("Server is running on http://localhost:37019") + }) + } +} \ No newline at end of file diff --git a/backend/src/main.ts b/backend/src/main.ts index 7ba3069..15ecaf6 100644 --- a/backend/src/main.ts +++ b/backend/src/main.ts @@ -1,72 +1,24 @@ -import config, { Config } from "./utils/config.js"; +import config from "./utils/config.js"; import fsp from "node:fs/promises"; import fs from "node:fs"; import { pipeline } from "node:stream/promises"; import { yauzl_promise } from "./utils/yauzl.promise.js"; -import express from "express"; -import multer from "multer"; -import cors from "cors" -import websocket, {WebSocketServer} from "ws" -import { createServer } from "node:http"; -const app = express(); -const upload = multer() -app.use(cors()) -app.use(express.json()) -const server = createServer(app); -const wss = new WebSocketServer({server}) -const tasks = new Map() -let timespm = 0; -let ws:websocket|undefined = undefined; -/* 对外API */ - // Express -app.post("/start",upload.single("file"),(req,res)=>{ - if (!req.file){ - return; - } - DeX(req.file.buffer) - timespm = Date.now(); - tasks.set(timespm,{status:"peding",result:undefined}); - res.json({taskId:timespm}) - //const buffer = Buffer.from(req.body); - //console.log(buffer); -}) +import { Core } from "./core.js"; +import { DeEarth } from "./utils/DeEarth.js"; +import { version_compare } from "./utils/utils.js"; +import { Forge } from "./modloader/forge.js"; +import { Minecraft } from "./modloader/minecraft.js"; -app.get('/getconfig',(req,res)=>{ - res.json(config) -}) +const core = new Core(config); -app.post('/writeconfig',(req,res)=>{ - Config.write_config(req.body) - res.json({status:200}) -}) - // WebSocket - wss.on("connection",(wsx)=>{ - ws = wsx; - }) +core.start(); -server.listen(37019,()=>{ - console.log("Server is running on http://localhost:37019") -}) +//console.log(version_compare("1.18.1","1.16.5")) -async function DeX(buffer: Buffer) { - /* 解压Zip */ - const zip = await yauzl_promise(buffer); - for await (const entry of zip) { - const ew = entry.fileName.endsWith('/') - if (ew){ - await fsp.mkdir(`./test/${entry.fileName}`,{recursive:true}) - } - if (!ew) { - const dirPath = `./test/${entry.fileName.substring(0, entry.fileName.lastIndexOf('/'))}`; - await fsp.mkdir(dirPath, { recursive: true }); - const stream = await entry.openReadStream; - const write = fs.createWriteStream(`./test/${entry.fileName}`); - await pipeline(stream, write); - } - if(ws){ - ws.send(JSON.stringify({status:"unzip",result:entry.fileName})) - } - } - /* 解压完成 */ - ws?.send(JSON.stringify({status:"changed",result:undefined})) -} \ No newline at end of file +// await new DeEarth("./mods").Main() + +// async function Dex(buffer: Buffer) { + +// } +// new Forge("1.20.1","47.3.10").setup() +await new Minecraft("forge","1.20.1").setup() \ No newline at end of file diff --git a/backend/src/modloader/fabric.ts b/backend/src/modloader/fabric.ts new file mode 100644 index 0000000..e69de29 diff --git a/backend/src/modloader/forge.ts b/backend/src/modloader/forge.ts new file mode 100644 index 0000000..5302925 --- /dev/null +++ b/backend/src/modloader/forge.ts @@ -0,0 +1,94 @@ +import got, { Got } from "got"; +import fs from "node:fs" +import fse from "fs-extra" +import { xfastdownload } from "../utils/utils.js"; +import { yauzl_promise } from "../utils/yauzl.promise.js"; + +interface Iforge{ + data:{ + MOJMAPS:{ + server:string + }, + MAPPINGS:{ + server:string + } + } +} + +interface Iversion{ + downloads:{ + server_mappings:{ + url:string + } + } +} + +export class Forge { + minecraft: string; + loaderVersion: string; + got: Got; + constructor(minecraft:string,loaderVersion:string){ + this.minecraft = minecraft; + this.loaderVersion = loaderVersion; + this.got = got.extend({ + prefixUrl: "https://bmclapi2.bangbang93.com", + headers: { "User-Agent": "DeEarthX" }, + }) + } + + async setup(){ + await this.installer() + await this.library() + // if (this.minecraft.startsWith("1.18")){ + // } + } + + async library(){ + const _downlist: [string,string][]= [] + const data = await fs.promises.readFile(`./forge/Forge-${this.minecraft}-${this.loaderVersion}.jar`) + const zip = await yauzl_promise(data) + for await(const entry of zip){ + if(entry.fileName === "version.json" || entry.fileName === "install_profile.json"){ //Libraries + JSON.parse((await entry.ReadEntry).toString()).libraries.forEach(async (e:any)=>{ + const t = e.downloads.artifact.path + _downlist.push([`https://bmclapi2.bangbang93.com/maven/${t}`,`./forge/libraries/${t}`]) + }) + } + if(entry.fileName === "install_profile.json"){ //MOJMAPS + /* 获取MOJMAPS */ + const json = JSON.parse((await entry.ReadEntry).toString()) as Iforge + const vjson = await this.got.get(`version/${this.minecraft}/json`).json() + console.log(`${new URL(vjson.downloads.server_mappings.url).pathname}`) + const mojpath = this.MTP(json.data.MOJMAPS.server) + _downlist.push([`https://bmclapi2.bangbang93.com/${new URL(vjson.downloads.server_mappings.url).pathname.slice(1)}`,`./forge/libraries/${mojpath}`]) + /* 获取MOJMAPS */ + + /*获取MAPPING*/ + const mappingobj = json.data.MAPPINGS.server + const path = this.MTP(mappingobj.replace(":mappings@txt","@zip")) + _downlist.push([`https://bmclapi2.bangbang93.com/maven/${path}`,`./forge/libraries/${path}`]) + /* 获取MAPPING */ + } + } + const downlist = [...new Set(_downlist)] + await xfastdownload(downlist) + } + + async installer(){ + const res = (await this.got.get(`forge/download?mcversion=${this.minecraft}&version=${this.loaderVersion}&category=installer&format=jar`)).rawBody; + await fse.outputFile(`./forge/Forge-${this.minecraft}-${this.loaderVersion}.jar`,res); + } + + + private MTP(string:string){ + const mjp = string.replace(/^\[|\]$/g, '') + const OriginalName = mjp.split("@")[0] + const x = OriginalName.split(":") + const mappingType = mjp.split('@')[1]; + if(x[3]){ + return `${x[0].replace(/\./g, '/')}/${x[1]}/${x[2]}/${x[1]}-${x[2]}-${x[3]}.${mappingType}` + }else{ + return `${x[0].replace(/\./g, '/')}/${x[1]}/${x[2]}/${x[1]}-${x[2]}.${mappingType}` + } + } +} \ No newline at end of file diff --git a/backend/src/modloader/index.ts b/backend/src/modloader/index.ts new file mode 100644 index 0000000..6f81649 --- /dev/null +++ b/backend/src/modloader/index.ts @@ -0,0 +1,15 @@ +interface XModloader { + setup: Promise +} +export function modloader(ml:string,mcv:string,mlv:string){ + switch (ml) { + case "fabric": + break; + case "forge": + break; + case "neoforge": + break; + default: + break; + } +} \ No newline at end of file diff --git a/backend/src/modloader/minecraft.ts b/backend/src/modloader/minecraft.ts new file mode 100644 index 0000000..20a85a1 --- /dev/null +++ b/backend/src/modloader/minecraft.ts @@ -0,0 +1,66 @@ +import fs from "node:fs" +import { fastdownload, version_compare } from "../utils/utils.js"; +import { yauzl_promise } from "../utils/yauzl.promise.js"; +import { pipeline } from "node:stream/promises"; +import got from "got"; + +interface ILInfo{ + libraries:{ + downloads:{ + artifact:{ + path:string + } + } + }[] +} + +export class Minecraft{ + loader: string; + minecraft: string; + constructor(loader:string,minecraft:string,){ + this.loader = loader; + this.minecraft = minecraft; + } + + async setup(){ + switch (this.loader){ + case "forge": + await this.forge_setup(); + break; + } + } + + async forge_setup(){ + const mcpath = `./forge/libraries/net/minecraft/server/${this.minecraft}/server-${this.minecraft}.jar` + await fastdownload([`https://bmclapi2.bangbang93.com/version/${this.minecraft}/server`,mcpath]) + if(version_compare(this.minecraft,"1.18") === 1){ + // 1.18.x + 依赖解压 + const zip = await yauzl_promise(await fs.promises.readFile(mcpath)) + for await(const entry of zip){ + //console.log(entry.fileName.replace("META-INF/libraries/","")) + if(entry.fileName.endsWith("/")){ + const dirPath = entry.fileName.replace("META-INF/libraries/","./forge/libraries/") + if (!fs.existsSync(dirPath)){ + await fs.promises.mkdir(dirPath, { recursive: true }); + } + } + if(entry.fileName.startsWith("META-INF/libraries/")&&!entry.fileName.endsWith("/")){ + console.log(entry.fileName) + const stream = await entry.openReadStream; + const write = fs.createWriteStream(`./forge/libraries/${entry.fileName.replace("META-INF/libraries/","")}`); + await pipeline(stream, write); + } + } + // 1.18.x + 依赖解压 + }else{ + //1.18.x - 依赖下载 + const json = await got.get(`https://bmclapi2.bangbang93.com/version/${this.minecraft}/json`) + .json() + json.libraries.forEach(async e=>{ + const path = e.downloads.artifact.path + await fastdownload([`https://bmclapi2.bangbang93.com/maven/${path}`,`./forge/libraries/${path}`]) + }) + //1.18.x - 依赖下载 + } + } +} \ No newline at end of file diff --git a/backend/src/modloader/neoforge.ts b/backend/src/modloader/neoforge.ts new file mode 100644 index 0000000..e69de29 diff --git a/backend/src/platform/curseforge.ts b/backend/src/platform/curseforge.ts index 787f09a..8d2b689 100644 --- a/backend/src/platform/curseforge.ts +++ b/backend/src/platform/curseforge.ts @@ -30,6 +30,9 @@ export class CurseForge implements XPlatform { async downloadfile(manifest: object, path: string): Promise { const local_manifest = manifest as CurseForgeManifest; + if (local_manifest.files.length === 0){ + return; + } const FileID = JSON.stringify({ fileIds: local_manifest.files.map( (file: { fileID: number }) => file.fileID diff --git a/backend/src/platform/index.ts b/backend/src/platform/index.ts index 6e0a6d6..fb3a5dd 100644 --- a/backend/src/platform/index.ts +++ b/backend/src/platform/index.ts @@ -1,5 +1,4 @@ import { CurseForge } from "./curseforge.js"; -import { MCBBS } from "./mcbbs.js"; import { Modrinth } from "./modrinth.js"; export interface XPlatform { @@ -22,21 +21,20 @@ export function platform(plat: string | undefined): XPlatform { case "modrinth": platform = new Modrinth(); break; - case "mcbbs": - platform = new MCBBS(); - break; + // case "mcbbs": + // platform = new MCBBS(); + // break; } return platform; } -export function what_platform(dud_files: Array) { - if (dud_files.includes("mcbbs.packmeta")) { - return "mcbbs"; - } else if (dud_files.includes("manifest.json")) { - return "curseforge"; - } else if (dud_files.includes("modrinth.index.json")) { - return "modrinth"; - } else { - return undefined; +export function what_platform(dud_files: string | "manifest.json" | "modrinth.index.json") { + switch (dud_files) { + case "manifest.json": + return "curseforge"; + case "modrinth.index.json": + return "modrinth"; + default: + return undefined } } diff --git a/backend/src/platform/mcbbs.ts b/backend/src/platform/mcbbs.ts deleted file mode 100644 index cb58a2a..0000000 --- a/backend/src/platform/mcbbs.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { CurseForgeManifest } from "./curseforge.js"; -import { modpack_info, XPlatform } from "./index.js"; - -interface MCBBSManifest extends CurseForgeManifest {} - -export class MCBBS implements XPlatform { - async getinfo(manifest: object): Promise { - const result: modpack_info = Object.create({}); - const local_manifest = manifest as MCBBSManifest; - if (result && local_manifest) - result.minecraft = local_manifest.minecraft.version; - const id = local_manifest.minecraft.modLoaders[0].id; - const loader_all = id.match(/(.*)-/) as RegExpMatchArray; - result.loader = loader_all[1]; - result.loader_version = id.replace(loader_all[0], ""); - return result; - } - - async downloadfile(urls: [string, string]): Promise {} -} diff --git a/backend/src/utils/DeEarth.ts b/backend/src/utils/DeEarth.ts new file mode 100644 index 0000000..b6ca50b --- /dev/null +++ b/backend/src/utils/DeEarth.ts @@ -0,0 +1,148 @@ +import fs from "node:fs" +import crypto from "node:crypto" +import { yauzl_promise } from "./yauzl.promise.js" +import got from "got" +import { Utils } from "./utils.js" +interface IMixins{ + name: string + data: string +} + +interface IFile{ + filename: string + hash: string + mixins: IMixins[] +} + +interface IHashRes{ + [key:string]:{ + project_id: string + } +} +interface IPjs{ + id:string, + client_side:string, + server_side:string +} +export class DeEarth{ + movepath: string + modspath: string + file: IFile[] + utils: Utils + constructor(modspath:string) { + this.utils = new Utils(); + this.movepath = "./.rubbish" + this.modspath = modspath + this.file = [] + } + + async Main(){ + if(!fs.existsSync(this.movepath)){ + fs.mkdirSync(this.movepath,{recursive:true}) + } + await this.getFile() + const hash = await this.Check_Hashes() + const mixins = await this.Check_Mixins() + const result = [...new Set(hash.concat(mixins))] + result.forEach(async e=>{ + await fs.promises.rename(`${this.modspath}/${e}`,`${this.movepath}/${e}`) + }) + } + + async Check_Hashes(){ + const cmap = new Map() + const fmap = new Map() + const hashes:string[] = [] + const files = this.file.forEach(e=>{ + hashes.push(e.hash); + cmap.set(e.hash,e.filename) + }) + const res = await got.post(this.utils.modrinth_url+"/v2/version_files",{ + headers:{ + "User-Agent": "DeEarth", + "Content-Type": "application/json" + }, + json:{ + hashes, + algorithm: "sha1" + } + }).json() + const x = Object.keys(res) + const arr = [] + const fhashes = [] + for(let i=0;i() + const result = [] //要删除的文件 + for(let i=0;i{ + try{ + const json = JSON.parse(e.data); + if(this._isClientMx(file,json)){ + result.push(file.filename) + } + }catch(e){} + }) + } + const _result = [...new Set(result)] + return _result; + } + async getFile():Promise{ + const files = this.getDir() + const arr = [] + for(let i=0;i{ //Get Mixins Info to check + if(e.fileName.endsWith(".mixins.json")&&!e.fileName.includes("/")){ + mxarr.push({name:e.fileName,data:(await e.ReadEntry).toString()}) + } + }) + arr.push({filename:file,hash:sha1,mixins:mxarr}) + } + this.file = arr + return arr; + } + private getDir():string[]{ + if(!fs.existsSync(this.movepath)){ + fs.mkdirSync(this.movepath) + } + const dirarr = fs.readdirSync(this.modspath).filter(e=>e.endsWith(".jar")).filter(e=>e.concat(this.modspath)); + return dirarr + } + + private _isClientMx(file:IFile,mixins:any){ + return (!("mixins" in mixins) || mixins.mixins.length === 0)&&(("client" in mixins) && (mixins.client.length !== 0))&&!file.filename.includes("lib") + } +} \ No newline at end of file diff --git a/backend/src/utils/config.ts b/backend/src/utils/config.ts index a0d2b60..578dbfc 100644 --- a/backend/src/utils/config.ts +++ b/backend/src/utils/config.ts @@ -1,5 +1,5 @@ -import fs from "fs"; -interface IConfig { +import fs from "node:fs"; +export interface IConfig { mirror: { bmclapi: boolean; mcimirror: boolean; diff --git a/backend/src/utils/utils.ts b/backend/src/utils/utils.ts index 31c8b93..111d35a 100644 --- a/backend/src/utils/utils.ts +++ b/backend/src/utils/utils.ts @@ -2,7 +2,7 @@ import pMap from "p-map"; import config from "./config.js"; import got from "got"; import pRetry from "p-retry"; -import fs from "fs"; +import fs from "node:fs"; import fse from "fs-extra"; export class Utils { @@ -24,18 +24,42 @@ export class Utils { } } +export function mavenToUrl( + coordinate: { split: (arg0: string) => [any, any, any, any] }, + base = "maven" +) { + const [g, a, v, ce] = coordinate.split(":"); + const [c, e = "jar"] = (ce || "").split("@"); + return `${base.replace(/\/$/, "")}/${g.replace( + /\./g, + "/" + )}/${a}/${v}/${a}-${v}${c ? "-" + c : ""}.${e}`; +} + +export function version_compare(v1: string, v2: string) { + const v1_arr = v1.split("."); + const v2_arr = v2.split("."); + for (let i = 0; i < v1_arr.length; i++) { + if (v1_arr[i] !== v2_arr[i]) { + return v1_arr[i] > v2_arr[i] ? 1 : -1; + } + } + return 0; +} + export async function fastdownload(data: [string, string]) { return await pMap( - data, - async (e) => { + [data], + async (e:any) => { try { await pRetry( async () => { if (!fs.existsSync(e[1])) { + /* const size: number = await (async () => { const head = ( await got.head( - e[0] /*.replace("https://mod.mcimirror.top","https://edge.forgecdn.net")*/, + e[0], { headers: { "user-agent": "DeEarthX" } } ) ).headers["content-length"]; @@ -44,7 +68,56 @@ export async function fastdownload(data: [string, string]) { } else { return 0; } - })(); + })();*/ + console.log(e) + await got + .get(e[0], { + responseType: "buffer", + headers: { + "user-agent": "DeEarthX", + }, + }) + .on("downloadProgress", (progress) => { + //bar.update(progress.transferred); + }) + .then((res) => { + fse.outputFileSync(e[1], res.rawBody); + }); + } + }, + { retries: 3 } + ); + } catch (e) { + //LOGGER.error({ err: e }); + } + }, + { concurrency: 16 } + ); +} + +export async function xfastdownload(data: [string, string][]) { + return await pMap( + data, + async (e:any) => { + try { + await pRetry( + async () => { + if (!fs.existsSync(e[1])) { + /* + const size: number = await (async () => { + const head = ( + await got.head( + e[0], + { headers: { "user-agent": "DeEarthX" } } + ) + ).headers["content-length"]; + if (head) { + return Number(head); + } else { + return 0; + } + })();*/ + console.log(e) await got .get(e[0], { responseType: "buffer", diff --git a/backend/src/utils/yauzl.promise.ts b/backend/src/utils/yauzl.promise.ts index 96503a3..d36cd30 100644 --- a/backend/src/utils/yauzl.promise.ts +++ b/backend/src/utils/yauzl.promise.ts @@ -3,6 +3,7 @@ import Stream from "node:stream" export interface IentryP extends yauzl.Entry { openReadStream: Promise; + ReadEntry: Promise; } export async function yauzl_promise(buffer: Buffer): Promise{ @@ -25,7 +26,8 @@ export async function yauzl_promise(buffer: Buffer): Promise{ getLastModDate: entry.getLastModDate, isEncrypted: entry.isEncrypted, isCompressed: entry.isCompressed, - openReadStream: _openReadStream(zip,entry) + openReadStream: _openReadStream(zip,entry), + ReadEntry: _ReadEntry(zip,entry) } entries.push(_entry) if (zip.entryCount === entries.length){ @@ -39,6 +41,24 @@ export async function yauzl_promise(buffer: Buffer): Promise{ }); } +async function _ReadEntry(zip:yauzl.ZipFile,entry:yauzl.Entry): Promise{ + return new Promise((resolve,reject)=>{ + zip.openReadStream(entry,(err,stream)=>{ + if (err){ + reject(err); + return; + } + const chunks: Buffer[] = []; + stream.on("data",(chunk)=>{ + chunks.push(chunk); + }) + stream.on("end",()=>{ + resolve(Buffer.concat(chunks)); + }) + }) + }) +} + async function _openReadStream(zip:yauzl.ZipFile,entry:yauzl.Entry): Promise{ return new Promise((resolve,reject)=>{ zip.openReadStream(entry,(err,stream)=>{ diff --git a/front/src/App.vue b/front/src/App.vue index b4a7054..d47e54d 100644 --- a/front/src/App.vue +++ b/front/src/App.vue @@ -3,6 +3,7 @@ import { h, ref } from 'vue'; import { MenuProps } from 'ant-design-vue'; import { SettingOutlined, UserOutlined, WindowsOutlined } from '@ant-design/icons-vue'; import { useRouter } from 'vue-router'; +import * as shell from '@tauri-apps/plugin-shell'; const router = useRouter(); const selectedKeys = ref(['main']); const items: MenuProps['items'] = [ diff --git a/front/src/component/Main.vue b/front/src/component/Main.vue index 824e99f..5bf0372 100644 --- a/front/src/component/Main.vue +++ b/front/src/component/Main.vue @@ -3,7 +3,6 @@ import { nextTick, ref, VNodeRef } from 'vue'; import { InboxOutlined } from '@ant-design/icons-vue'; import { message, StepsProps } from 'ant-design-vue'; import type { UploadFile, UploadChangeParam, Upload } from 'ant-design-vue'; -import * as shell from '@tauri-apps/plugin-shell'; interface IWSM { status: "unzip"|"pending"|"changed", result: string @@ -63,7 +62,7 @@ function reactFL() { isDisabled.value = false; } /* 获取文件区 */ -shell.Command.create('core',['start']).spawn() +//shell.Command.create('core',['start']).spawn() function runDeEarthX(data: Blob) { console.log(data) const fd = new FormData(); diff --git a/front/src/component/Setting.vue b/front/src/component/Setting.vue index 3ff833b..a8fd50d 100644 --- a/front/src/component/Setting.vue +++ b/front/src/component/Setting.vue @@ -1,6 +1,5 @@