
{ "name": "rabid-oil-clean-6o8jz", "productName": "rabid-oil-clean-6o8jz", "description": "My Electron application description", "keywords": [], "main": "./main.js", "version": "1.0.0", "author": "liubo", "scripts": { "start": "electron ." }, "dependencies": {}, "devDependencies": { "electron": "20.0.1" }}
<!DOCTYPE html><html><head> <meta charset="UTF-8"> <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --> <!-- <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'"> --> <title>Hello World!</title></head><body> <h1>Hello World!</h1> We are using Node.js <span id="node-version"></span>, Chromium <span id="chrome-version"></span>, and Electron <span id="electron-version"></span>. <br /> <button id="newWIn">新建窗口</button> <br /> <button id="upload1">下载1</button> <button id="upload2">下载2</button> <br /> <button id="cancel1">取消1</button> <button id="cancel2">取消2</button> <br /> <div> <div>下载任务</div> <div id="downloads"> </div> </div> <h1 id="h1"></h1> <!-- You can also require other files to run in this process --> <script src="./child.js"></script> <style> * { padding: 0; margin: 0; word-break: break-all; } </style></body></html>
// This file is required by the index.html file and will// be executed in the renderer process for that window.// No Node.js APIs are available in this process because// `nodeIntegration` is turned off. Use `preload.js` to// selectively enable features needed in the rendering// process.// All of the Node.js APIs are available in the preload process.// It has the same sandbox as a Chrome extension.const { ipcRenderer, contextBridge } = require("electron");window.addEventListener("DOMContentLoaded", () => { const replaceText = (selector, text) => { const element = document.getElementById(selector); if (element) element.innerText = text; }; for (const type of ["chrome", "node", "electron"]) { replaceText(`${type}-version`, process.versions[type]); }});window.app = { ipcReceive: (channel, callback) => { ipcRenderer.on(channel, (eventt, ...rest) => { callback(...rest); }); }, ipcSend: (channel, ...msg) => { ipcRenderer.send(channel, ...msg); }, ipcInvoke: (channel, ...msg) => { return ipcRenderer.invoke(channel, ...msg); },}let newWIn = document.querySelector("#newWIn");let cancel1 = document.querySelector("#cancel1");let cancel2 = document.querySelector("#cancel2");let upload1 = document.querySelector("#upload1");let upload2 = document.querySelector("#upload2");let h1 = document.querySelector("#h1");let downloads = document.querySelector("#downloads");(async function () { let res = await window.app.ipcInvoke("getCount"); console.log(res, "-------------"); h1.innerHTML = res;})();newWIn.addEventListener("click", () => { window.app.ipcInvoke("createWindow");});cancel1.addEventListener("click", () => { window.app.ipcInvoke("cancel", { id: 1 });});cancel2.addEventListener("click", () => { window.app.ipcInvoke("cancel", { id: 2 });});upload1.addEventListener("click", () => { window.app.ipcInvoke("upload", { id: 1, url: "https://download.jetbrains.com.cn/python/pycharm-professional-2022.2.1.exe", });});upload2.addEventListener("click", () => { window.app.ipcInvoke("upload", { id: 2, url: "https://download.jetbrains.com.cn/python/pycharm-professional-2022.2.1.exe", });});window.app.ipcReceive("data-update", (data) => { console.log(data, "-------------"); h1.innerHTML = data;});
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --> <!-- <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'"> --> <title>Hello World!</title> </head> <body> <h1>Hello World!</h1> We are using Node.js <span id="node-version"></span>, Chromium <span id="chrome-version"></span>, and Electron <span id="electron-version"></span>. <button id="newWIn">新建窗口</button> <br /> <button id="upload1">下载1</button> <button id="upload2">下载2</button> <br /> <button id="cancel1">取消1</button> <button id="cancel2">取消2</button> <br /> <div> <div>下载任务</div> <div id="downloads"> </div> </div> <h1 id="h1"></h1> <!-- You can also require other files to run in this process --> <script src="./renderer.js"></script> <style> * { padding: 0; margin: 0; word-break: break-all; } </style> </body></html>
// Modules to control application life and create native browser windowconst { app, BrowserWindow, ipcMain } = require('electron')const path = require('path')const http = require('http')const https = require('https')ipcMain.handle('createWindow', () => { createWindow()})let manage = []let count = 0ipcMain.handle('upload', (event, { id, url }) => { console.log(id, url) download(id, url)})function filter(manage) { let res = [] for (let cur of manage) { let could = {} for (let n of Object.keys(cur)) { if (n === 'client') { could[n] = null } else { could[n] = cur[n] } } res.push(could) } return res}function download(id, url) { let run = manage.find(n => n.id === id) if (run && run.status === 'runing') return let cur = run ? run : { id, url, persent: 0, // controller, client: null, status: 'runing' } if (!run) { manage.push(cur) } else { run.persent = 0 run.status = 'runing' } debugger; const options = { method: "GET", responseType: "blob", // signal, headers: { // "Content-Type": "application/json" }, }; console.log(url, options); if (url.startsWith("https://")) { const clientRequest = https.request(url, options, (incomingMessage) => { debugger; console.log(`状态码: ${incomingMessage.statusCode}`); let contentLength = incomingMessage.headers["content-length"]; let load = 0; incomingMessage.on("data", (d) => { // console.log(incomingMessage) debugger; load += d.length; // process.stdout.write(d); let persent = Math.floor((load / contentLength) * 10000) / 100; console.log(d.length, load, contentLength, `${persent}%`); cur.persent = persent let res = filter(manage) notify(JSON.stringify(res)) }); incomingMessage.on("end", () => { console.log("end"); }); }); cur.client = clientRequest clientRequest.end(); clientRequest.on("error", (error) => { console.error(error); }); clientRequest.on("close", (val) => { console.log("close"); }); } else { const clientRequest = http.request(url, options, (incomingMessage) => { debugger; console.log(`状态码: ${incomingMessage.statusCode}`); let contentLength = incomingMessage.headers["content-length"]; let load = 0; incomingMessage.on("data", (d) => { // console.log(incomingMessage) debugger; load += d.length; // process.stdout.write(d); let persent = Math.floor((load / contentLength) * 10000) / 100; console.log(d.length, load, contentLength, `${persent}%`); cur.persent = persent let res = filter(manage) notify(JSON.stringify(res)) }); incomingMessage.on("end", () => { console.log("end"); }); }); cur.client = clientRequest clientRequest.end(); clientRequest.on("error", (error) => { console.error(error); }); clientRequest.on("close", (val) => { console.log("close"); }); }}/* 通知给窗口 */function notify(message) { let wins = BrowserWindow.getAllWindows() for (let win of wins) { // console.log(win) win.webContents.send('data-update', message) }}ipcMain.handle('cancel', (event, { id }) => { console.log(id) let cur = manage.find(n => n.id === id) // cur.controller.abort(); cur.status = 'cancel' cur.client.destroy() let res = filter(manage) notify(JSON.stringify(res))})ipcMain.handle('getCount', () => { return count})function createWindow() { // Create the browser window. const mainWindow = new BrowserWindow({ width: 800, height: 600, webPreferences: { preload: path.join(__dirname, 'preload.js') } }) // and load the index.html of the app. mainWindow.loadFile('index.html') // Open the DevTools. // mainWindow.webContents.openDevTools()}// This method will be called when Electron has finished// initialization and is ready to create browser windows.// Some APIs can only be used after this event occurs.app.whenReady().then(() => { createWindow() app.on('activate', function () { // On macOS it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. if (BrowserWindow.getAllWindows().length === 0) createWindow() })})// Quit when all windows are closed, except on macOS. There, it's common// for applications and their menu bar to stay active until the user quits// explicitly with Cmd + Q.app.on('window-all-closed', function () { if (process.platform !== 'darwin') app.quit()})// In this file you can include the rest of your app's specific main process// code. You can also put them in separate files and require them here.
// All of the Node.js APIs are available in the preload process.// It has the same sandbox as a Chrome extension.const { ipcRenderer, contextBridge } = require("electron");window.addEventListener('DOMContentLoaded', () => { const replaceText = (selector, text) => { const element = document.getElementById(selector) if (element) element.innerText = text } for (const type of ['chrome', 'node', 'electron']) { replaceText(`${type}-version`, process.versions[type]) }})contextBridge.exposeInMainWorld('app', { ipcReceive: (channel, callback) => { ipcRenderer.on(channel, (eventt, ...rest) => { callback(...rest) }) }, ipcSend: (channel, ...msg) => { ipcRenderer.send(channel, ...msg) }, ipcInvoke: (channel, ...msg) => { return ipcRenderer.invoke(channel, ...msg) },})
// This file is required by the index.html file and will// be executed in the renderer process for that window.// No Node.js APIs are available in this process because// `nodeIntegration` is turned off. Use `preload.js` to// selectively enable features needed in the rendering// process.let newWIn = document.querySelector('#newWIn')let cancel1 = document.querySelector('#cancel1')let cancel2 = document.querySelector('#cancel2')let upload1 = document.querySelector('#upload1')let upload2 = document.querySelector('#upload2')let h1 = document.querySelector('#h1')let downloads = document.querySelector("#downloads") ; (async function () { let res = await window.app.ipcInvoke('getCount') console.log(res, '-------------') h1.innerHTML = res })()newWIn.addEventListener('click', () => { window.app.ipcInvoke('createWindow')})cancel1.addEventListener('click', () => { window.app.ipcInvoke('cancel', { id: 1 })})cancel2.addEventListener('click', () => { window.app.ipcInvoke('cancel', { id: 2 })})upload1.addEventListener('click', () => { window.app.ipcInvoke('upload', { id: 1, url: 'https://download.jetbrains.com.cn/python/pycharm-professional-2022.2.1.exe' })})upload2.addEventListener('click', () => { window.app.ipcInvoke('upload', { id: 2, url: 'https://download.jetbrains.com.cn/python/pycharm-professional-2022.2.1.exe' })})window.app.ipcReceive('data-update', (data) => { console.log(data, '-------------') h1.innerHTML = data})