Skip to content

Commit b3a0be0

Browse files
badamsdevelar
authored andcommitted
feat: Adding download-progress event to AutoUpdater (#1042)
Closes #958
1 parent 96895cf commit b3a0be0

File tree

5 files changed

+74
-4
lines changed

5 files changed

+74
-4
lines changed

nsis-auto-updater/src/NsisUpdater.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,13 @@ export class NsisUpdater extends EventEmitter {
148148
async downloadUpdate() {
149149
const versionInfo = this.versionInfo
150150
const fileInfo = this.fileInfo
151+
const downloadOptions: any = {
152+
onProgress: (progress: any) => this.emit("download-progress", {}, progress)
153+
}
154+
155+
if (fileInfo && fileInfo.sha2) {
156+
downloadOptions["sha2"] = fileInfo.sha2
157+
}
151158

152159
if (versionInfo == null || fileInfo == null) {
153160
const message = "Please check update first"
@@ -157,7 +164,7 @@ export class NsisUpdater extends EventEmitter {
157164
}
158165

159166
return mkdtemp(`${path.join(tmpdir(), "up")}-`)
160-
.then(it => download(fileInfo.url, path.join(it, fileInfo.name), fileInfo.sha2 == null ? null : {sha2: fileInfo.sha2}))
167+
.then(it => download(fileInfo.url, path.join(it, fileInfo.name), downloadOptions))
161168
.then(it => {
162169
this.setupPath = it
163170
this.addQuitHandler()

nsis-auto-updater/src/electronHttpExecutor.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { net } from "electron"
33
import { createWriteStream, ensureDir } from "fs-extra-p"
44
import BluebirdPromise from "bluebird-lst-c"
55
import * as path from "path"
6-
import { HttpExecutor, DownloadOptions, HttpError, DigestTransform, checkSha2 } from "../../src/util/httpExecutor"
6+
import { HttpExecutor, DownloadOptions, HttpError, DigestTransform, checkSha2, calculateDownloadProgress } from "../../src/util/httpExecutor"
77
import { Url } from "url"
88
import { safeLoad } from "js-yaml"
99
import _debug from "debug"
@@ -69,7 +69,7 @@ export class ElectronHttpExecutor implements HttpExecutor {
6969
// user-agent must be specified, otherwise some host can return 401 unauthorised
7070

7171
//FIXME hack, the electron typings specifies Protocol with capital but the code actually uses with small case
72-
const requestOpts = {
72+
const requestOpts = {
7373
protocol: parsedUrl.protocol,
7474
hostname: parsedUrl.hostname,
7575
path: parsedUrl.path,
@@ -99,6 +99,16 @@ export class ElectronHttpExecutor implements HttpExecutor {
9999
return
100100
}
101101

102+
if (options.onProgress != null) {
103+
const total = parseInt(String(safeGetHeader(response, "content-length")), 10)
104+
const start = Date.now()
105+
let transferred = 0
106+
107+
response.on("data", (chunk: any) => {
108+
transferred = calculateDownloadProgress(total, start, transferred, chunk, options.onProgress)
109+
})
110+
}
111+
102112
ensureDirPromise
103113
.then(() => {
104114
const fileOut = createWriteStream(destination)

src/util/httpExecutor.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Transform } from "stream"
55
export interface DownloadOptions {
66
skipDirCreation?: boolean
77
sha2?: string
8+
onProgress?(progress: any): void
89
}
910

1011
export class HttpExecutorHolder {
@@ -75,4 +76,15 @@ export function checkSha2(sha2Header: string | null | undefined, sha2: string |
7576
}
7677
}
7778
return true
79+
}
80+
81+
export function calculateDownloadProgress(total: number, start: number, transferred: number, chunk: any, callback: any): number {
82+
transferred += chunk.length
83+
callback({
84+
total: total,
85+
transferred: transferred,
86+
percent: ((transferred / total) * 100).toFixed(2),
87+
bytesPerSecond: Math.round(transferred / ((Date.now() - start) / 1000))
88+
})
89+
return transferred
7890
}

src/util/nodeHttpExecutor.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import BluebirdPromise from "bluebird-lst-c"
66
import * as path from "path"
77
import { homedir } from "os"
88
import { parse as parseIni } from "ini"
9-
import { HttpExecutor, DownloadOptions, HttpError, DigestTransform, checkSha2 } from "./httpExecutor"
9+
import { HttpExecutor, DownloadOptions, HttpError, DigestTransform, checkSha2, calculateDownloadProgress} from "./httpExecutor"
1010
import { Url } from "url"
1111
import { RequestOptions } from "https"
1212
import { safeLoad } from "js-yaml"
@@ -95,6 +95,18 @@ export class NodeHttpExecutor implements HttpExecutor {
9595
return
9696
}
9797

98+
if (options.onProgress != null) {
99+
const total = parseInt(response.headers["content-length"], 10)
100+
const start = Date.now()
101+
let transferred = 0
102+
103+
response.on("data", (chunk: any) => {
104+
transferred = calculateDownloadProgress(total, start, transferred, chunk, options.onProgress)
105+
})
106+
107+
response.pause()
108+
}
109+
98110
ensureDirPromise
99111
.then(() => {
100112
const fileOut = createWriteStream(destination)

test/src/nsisUpdaterTest.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,35 @@ test("test error", async () => {
171171
expect(actualEvents).toMatchSnapshot()
172172
})
173173

174+
test("test download progress", async () => {
175+
const tmpDir = new TmpDir()
176+
const testResourcesPath = await tmpDir.getTempFile("update-config")
177+
await outputFile(path.join(testResourcesPath, "app-update.yml"), safeDump(<GenericServerOptions>{
178+
provider: "generic",
179+
url: "https://develar.s3.amazonaws.com/test",
180+
}))
181+
g.__test_resourcesPath = testResourcesPath
182+
const updater: NsisUpdater = new NsisUpdaterClass()
183+
updater.autoDownload = false
184+
185+
const progressEvents: Array<any> = []
186+
187+
updater.addListener("download-progress", (e: any, progress: any) => {
188+
progressEvents.push(progress)
189+
})
190+
191+
await updater.checkForUpdates()
192+
await updater.downloadUpdate()
193+
194+
expect(progressEvents.length).toBeGreaterThanOrEqual(1)
195+
196+
const lastEvent = progressEvents.pop()
197+
198+
expect(parseInt(lastEvent.percent, 10)).toBe(100)
199+
expect(lastEvent.bytesPerSecond).toBeGreaterThan(1)
200+
expect(lastEvent.transferred).toBe(lastEvent.total)
201+
})
202+
174203
function trackEvents(updater: NsisUpdater) {
175204
const actualEvents: Array<string> = []
176205
for (const eventName of ["checking-for-update", "update-available", "update-downloaded", "error"]) {

0 commit comments

Comments
 (0)