forked from JCMais/node-libcurl
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy path13-progress-callback.js
127 lines (101 loc) · 3.18 KB
/
13-progress-callback.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/**
* Copyright (c) Jonathan Cardoso Machado. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* Example that shows the use of the the progress callback.
* The progress bar is made using the node-progress (https://github.com/visionmedia/node-progress) module.
* You need to install that package to make it work.
*/
const path = require('path')
const fs = require('fs')
const ProgressBar = require('progress')
const { Curl, CurlFeature } = require('../dist')
const curl = new Curl()
const url = process.argv[2] || 'http://ovh.net/files/100Mio.dat'
const complete = '\u001b[42m \u001b[0m'
const incomplete = '\u001b[43m \u001b[0m'
const outputFile = path.resolve(__dirname, 'result.out')
const speedInfo = {
timeStart: [0, 0],
timeSpent: 0,
timeLast: [0, 0],
counter: 0,
speedAverage: 0,
}
let lastdlnow = 0
let bar = null
if (fs.existsSync(outputFile)) {
fs.unlinkSync(outputFile)
}
curl.setOpt('URL', url)
curl.setOpt(Curl.option.NOPROGRESS, false)
//Since we are downloading a large file, disable internal storage
// used for automatic http data/headers parsing.
//Because of that, the end event will receive null for both data/header arguments.
curl.enable(CurlFeature.NoStorage)
// utility function to convert process.hrtime() call result to ms.
function hrtimeToMs(hrtimeTouple) {
return (hrtimeTouple[0] * 1000 + hrtimeTouple[1] / 1e6) | 0
}
// The option XFERINFOFUNCTION was introduced in curl version 7.32.0,
// versions older than that should use PROGRESSFUNCTION.
// if you don't want to mess with version numbers,
// there is the following helper method to set the progress cb.
curl.setProgressCallback((dltotal, dlnow /*, ultotal, ulnow*/) => {
if (dltotal === 0) {
return 0
}
if (!bar) {
console.log()
bar = new ProgressBar(
'Downloading [:bar] :percent :etas - Avg :speed Kb/s',
{
complete: complete,
incomplete: incomplete,
width: 20,
total: dltotal,
},
)
}
speedInfo.timeSpent = process.hrtime(speedInfo.timeStart)
const now = process.hrtime()
//update no more than 1 time per second, or if it's the last call to the callback.
if (
((hrtimeToMs(speedInfo.timeLast) / 1000) | 0) ===
((hrtimeToMs(now) / 1000) | 0) &&
dlnow !== dltotal
) {
return 0
}
speedInfo.timeLast = now
//average speed
speedInfo.speedAverage =
dlnow / (speedInfo.timeSpent[0] > 0 ? speedInfo.timeSpent[0] : 1)
if (bar) {
bar.tick(dlnow - lastdlnow, {
speed: (speedInfo.speedAverage / 1000).toFixed(2),
})
lastdlnow = dlnow
}
return 0
})
// This is basically the same than the `data` event emitted on
// the `Curl` instance, but keep in mind that here the return value is considered.
// You must return the amount of data that was written.
curl.setOpt(Curl.option.WRITEFUNCTION, (chunk) => {
fs.appendFileSync(outputFile, chunk)
return chunk.length
})
curl.on('end', () => {
console.log('Download ended')
curl.close()
})
curl.on('error', (error) => {
console.log('Failed to download file', error)
curl.close()
})
speedInfo.timeStart = process.hrtime()
curl.perform()