w-converhp 1.0.39 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci-test.yml +1 -1
- package/README.md +188 -169
- package/dist/w-converhp-client.umd.js +2 -2
- package/dist/w-converhp-client.umd.js.map +1 -1
- package/dist/w-converhp-server.umd.js +2 -2
- package/dist/w-converhp-server.umd.js.map +1 -1
- package/docs/WConverhpClient.html +9 -809
- package/docs/WConverhpClient.mjs.html +465 -529
- package/docs/WConverhpServer.html +238 -1340
- package/docs/WConverhpServer.mjs.html +590 -392
- package/docs/index.html +2 -2
- package/package.json +7 -7
- package/scla.mjs +31 -49
- package/sclb.mjs +31 -48
- package/sclc.mjs +42 -0
- package/script.txt +18 -0
- package/src/WConverhpClient.mjs +463 -527
- package/src/WConverhpServer.mjs +588 -390
- package/srv.mjs +24 -46
- package/web.html +93 -76
- package/zdata.b1 +0 -1
package/src/WConverhpServer.mjs
CHANGED
|
@@ -1,19 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+
import path from 'path'
|
|
2
|
+
import fs from 'fs'
|
|
2
3
|
import Hapi from '@hapi/hapi'
|
|
3
4
|
import Inert from '@hapi/inert' //提供靜態檔案
|
|
4
|
-
import events from 'events'
|
|
5
5
|
import stream from 'stream'
|
|
6
|
-
import get from 'lodash-es/get'
|
|
7
|
-
import map from 'lodash-es/map'
|
|
8
|
-
import each from 'lodash-es/each'
|
|
9
|
-
import cloneDeep from 'lodash-es/cloneDeep'
|
|
6
|
+
import get from 'lodash-es/get.js'
|
|
10
7
|
import genPm from 'wsemi/src/genPm.mjs'
|
|
11
|
-
import alive from 'wsemi/src/alive.mjs'
|
|
12
|
-
import isstr from 'wsemi/src/isstr.mjs'
|
|
13
8
|
import iseobj from 'wsemi/src/iseobj.mjs'
|
|
9
|
+
import isestr from 'wsemi/src/isestr.mjs'
|
|
10
|
+
import isp0int from 'wsemi/src/isp0int.mjs'
|
|
11
|
+
import ispint from 'wsemi/src/ispint.mjs'
|
|
12
|
+
import isearr from 'wsemi/src/isearr.mjs'
|
|
13
|
+
import isbol from 'wsemi/src/isbol.mjs'
|
|
14
|
+
import isfun from 'wsemi/src/isfun.mjs'
|
|
15
|
+
import ispm from 'wsemi/src/ispm.mjs'
|
|
16
|
+
import cint from 'wsemi/src/cint.mjs'
|
|
17
|
+
import evem from 'wsemi/src/evem.mjs'
|
|
14
18
|
import obj2u8arr from 'wsemi/src/obj2u8arr.mjs'
|
|
15
19
|
import u8arr2obj from 'wsemi/src/u8arr2obj.mjs'
|
|
16
|
-
import
|
|
20
|
+
import fsIsFolder from 'wsemi/src/fsIsFolder.mjs'
|
|
21
|
+
import fsCreateFolder from 'wsemi/src/fsCreateFolder.mjs'
|
|
22
|
+
import fsIsFile from 'wsemi/src/fsIsFile.mjs'
|
|
23
|
+
import fsDeleteFile from 'wsemi/src/fsDeleteFile.mjs'
|
|
17
24
|
|
|
18
25
|
|
|
19
26
|
/**
|
|
@@ -21,78 +28,63 @@ import iser from 'wsemi/src/iser.mjs'
|
|
|
21
28
|
*
|
|
22
29
|
* @class
|
|
23
30
|
* @param {Object} [opt={}] 輸入設定物件,預設{}
|
|
24
|
-
* @param {Integer} [opt.port=8080] 輸入Hapi伺服器所在port
|
|
25
|
-
* @param {
|
|
26
|
-
* @
|
|
31
|
+
* @param {Integer} [opt.port=8080] 輸入Hapi伺服器所在port正整數,預設8080
|
|
32
|
+
* @param {Boolean} [opt.useInert=true] 輸入是否提供瀏覽pathStaticFiles資料夾內檔案之布林值,預設true
|
|
33
|
+
* @param {String} [opt.pathStaticFiles='dist'] 輸入當useInert=true時提供瀏覽資料夾字串,預設'dist'
|
|
34
|
+
* @param {String} [opt.apiName='api'] 輸入API名稱字串,預設'api'
|
|
35
|
+
* @param {String} [opt.pathUploadTemp='./uploadTemp'] 輸入暫時存放切片上傳檔案資料夾字串,預設'./uploadTemp'
|
|
36
|
+
* @param {Function} [opt.funCheck=()=>{return true}] 輸入呼叫API時檢測函數,預設()=>{return true}
|
|
37
|
+
* @param {Array} [opt.corsOrigins=['*']] 輸入允許跨域網域陣列,若給予['*']代表允許全部,預設['*']
|
|
38
|
+
* @param {Integer} [opt.delayForBasic=0] 輸入基本API用延遲響應時間,單位ms,預設0
|
|
39
|
+
* @param {Integer} [opt.delayForSlice=100] 輸入切片上傳檔案API用延遲響應時間,單位ms,預設100
|
|
40
|
+
* @param {Boolean} [opt.serverHapi=null] 輸入外部提供Hapi伺服器物件,預設null
|
|
41
|
+
* @returns {Object} 回傳通訊物件,可監聽事件execute、upload、handler
|
|
27
42
|
* @example
|
|
28
43
|
*
|
|
44
|
+
* import _ from 'lodash-es'
|
|
29
45
|
* import WConverhpServer from 'w-converhp/dist/w-converhp-server.umd.js'
|
|
30
46
|
*
|
|
31
47
|
* let opt = {
|
|
32
48
|
* port: 8080,
|
|
33
49
|
* apiName: 'api',
|
|
50
|
+
* pathStaticFiles: '.', //要存取專案資料夾下web.html, 故不能給dist
|
|
51
|
+
* funCheck: () => {
|
|
52
|
+
* return true
|
|
53
|
+
* },
|
|
34
54
|
* }
|
|
35
55
|
*
|
|
36
56
|
* //new
|
|
37
57
|
* let wo = new WConverhpServer(opt)
|
|
38
58
|
*
|
|
39
|
-
* wo.on('open', function() {
|
|
40
|
-
* console.log(`Server[port:${opt.port}]: open`)
|
|
41
|
-
*
|
|
42
|
-
* //broadcast
|
|
43
|
-
* let n = 0
|
|
44
|
-
* setInterval(() => {
|
|
45
|
-
* n += 1
|
|
46
|
-
* let o = {
|
|
47
|
-
* text: `server broadcast hi(${n})`,
|
|
48
|
-
* data: new Uint8Array([66, 97, 115]), //support Uint8Array data
|
|
49
|
-
* }
|
|
50
|
-
* wo.broadcast(o, function (prog) {
|
|
51
|
-
* console.log('broadcast prog', prog)
|
|
52
|
-
* })
|
|
53
|
-
* }, 1000)
|
|
54
|
-
*
|
|
55
|
-
* })
|
|
56
|
-
* wo.on('error', function(err) {
|
|
57
|
-
* console.log(`Server[port:${opt.port}]: error`, err)
|
|
58
|
-
* })
|
|
59
|
-
* wo.on('clientChange', function(num) {
|
|
60
|
-
* console.log(`Server[port:${opt.port}]: now clients: ${num}`)
|
|
61
|
-
* })
|
|
62
|
-
* wo.on('clientEnter', function(clientId, data) {
|
|
63
|
-
* console.log(`Server[port:${opt.port}]: client enter: ${clientId}`)
|
|
64
|
-
*
|
|
65
|
-
* //deliver
|
|
66
|
-
* wo.deliver(clientId, `server deliver hi(${clientId})`)
|
|
67
|
-
*
|
|
68
|
-
* })
|
|
69
|
-
* wo.on('clientLeave', function(clientId, data) {
|
|
70
|
-
* console.log(`Server[port:${opt.port}]: client leave: ${clientId}`)
|
|
71
|
-
* })
|
|
72
59
|
* wo.on('execute', function(func, input, pm) {
|
|
73
|
-
* //console.log(`Server[port:${opt.port}]: execute`, func, input)
|
|
60
|
+
* // console.log(`Server[port:${opt.port}]: execute`, func, input)
|
|
74
61
|
* console.log(`Server[port:${opt.port}]: execute`, func)
|
|
75
62
|
*
|
|
76
63
|
* try {
|
|
77
64
|
*
|
|
78
65
|
* if (func === 'add') {
|
|
79
66
|
*
|
|
80
|
-
* //save
|
|
81
67
|
* if (_.get(input, 'p.d.u8a', null)) {
|
|
82
|
-
*
|
|
83
|
-
* // console.log('writeFileSync input.p.d.name', input.p.d.name)
|
|
68
|
+
* console.log('input.p.d.u8a', input.p.d.u8a)
|
|
84
69
|
* }
|
|
85
70
|
*
|
|
86
71
|
* let r = {
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
72
|
+
* _add: input.p.a + input.p.b,
|
|
73
|
+
* _data: [11, 22.22, 'abc', { x: '21', y: 65.43, z: 'test中文' }],
|
|
74
|
+
* _bin: {
|
|
90
75
|
* name: 'zdata.b2',
|
|
91
76
|
* u8a: new Uint8Array([66, 97, 115]),
|
|
92
|
-
* //
|
|
77
|
+
* // name: '100mb.7z',
|
|
78
|
+
* // u8a: new Uint8Array(fs.readFileSync('D:\\開源-JS-006-2-w-converhp\\_temp\\100mb.7z')),
|
|
79
|
+
* // name: '500mb.7z',
|
|
80
|
+
* // u8a: new Uint8Array(fs.readFileSync('D:\\開源-JS-006-2-w-converhp\\_temp\\500mb.7z')),
|
|
81
|
+
* // name: '1000mb.7z',
|
|
82
|
+
* // u8a: new Uint8Array(fs.readFileSync('D:\\開源-JS-006-2-w-converhp\\_temp\\1000mb.7z')),
|
|
93
83
|
* },
|
|
94
84
|
* }
|
|
85
|
+
*
|
|
95
86
|
* pm.resolve(r)
|
|
87
|
+
*
|
|
96
88
|
* }
|
|
97
89
|
* else {
|
|
98
90
|
* console.log('invalid func')
|
|
@@ -106,72 +98,93 @@ import iser from 'wsemi/src/iser.mjs'
|
|
|
106
98
|
* }
|
|
107
99
|
*
|
|
108
100
|
* })
|
|
109
|
-
* wo.on('
|
|
110
|
-
* console.log(`Server[port:${opt.port}]:
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
101
|
+
* wo.on('upload', function(input, pm) {
|
|
102
|
+
* console.log(`Server[port:${opt.port}]: upload`, input)
|
|
103
|
+
*
|
|
104
|
+
* try {
|
|
105
|
+
* let output = input
|
|
106
|
+
* pm.resolve(output)
|
|
107
|
+
* }
|
|
108
|
+
* catch (err) {
|
|
109
|
+
* console.log('execute error', err)
|
|
110
|
+
* pm.reject('execute error')
|
|
111
|
+
* }
|
|
112
|
+
*
|
|
114
113
|
* })
|
|
115
114
|
* wo.on('handler', function(data) {
|
|
116
115
|
* // console.log(`Server[port:${opt.port}]: handler`, data)
|
|
117
116
|
* })
|
|
118
117
|
*
|
|
119
|
-
*
|
|
120
118
|
*/
|
|
121
119
|
function WConverhpServer(opt = {}) {
|
|
122
|
-
let broadcastMessages = {}
|
|
123
120
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
if (!
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
if (!opt.apiName) {
|
|
130
|
-
opt.apiName = 'api'
|
|
121
|
+
//port
|
|
122
|
+
let port = get(opt, 'port')
|
|
123
|
+
if (!ispint(port)) {
|
|
124
|
+
port = 8080
|
|
131
125
|
}
|
|
132
126
|
|
|
127
|
+
//useInert
|
|
128
|
+
let useInert = get(opt, 'useInert')
|
|
129
|
+
if (!isbol(useInert)) {
|
|
130
|
+
useInert = true
|
|
131
|
+
}
|
|
133
132
|
|
|
134
|
-
//
|
|
135
|
-
let
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
let ea = alive()
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
//ea broadcastMessages
|
|
143
|
-
setInterval(() => {
|
|
133
|
+
//pathStaticFiles
|
|
134
|
+
let pathStaticFiles = get(opt, 'pathStaticFiles')
|
|
135
|
+
if (!isestr(pathStaticFiles)) {
|
|
136
|
+
pathStaticFiles = 'dist'
|
|
137
|
+
}
|
|
144
138
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
139
|
+
//apiName
|
|
140
|
+
let apiName = get(opt, 'apiName')
|
|
141
|
+
if (!isestr(apiName)) {
|
|
142
|
+
apiName = 'api'
|
|
143
|
+
}
|
|
148
144
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
//console.log('clientIds', clientIds)
|
|
145
|
+
//apiSliceName
|
|
146
|
+
let apiSliceName = `${apiName}slc`
|
|
152
147
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
148
|
+
//pathUploadTemp
|
|
149
|
+
let pathUploadTemp = get(opt, 'pathUploadTemp')
|
|
150
|
+
if (!isestr(pathUploadTemp)) {
|
|
151
|
+
pathUploadTemp = './uploadTemp'
|
|
152
|
+
}
|
|
153
|
+
if (!fsIsFolder(pathUploadTemp)) {
|
|
154
|
+
fsCreateFolder(pathUploadTemp)
|
|
155
|
+
}
|
|
160
156
|
|
|
161
|
-
|
|
157
|
+
//funCheck
|
|
158
|
+
let funCheck = get(opt, 'funCheck')
|
|
159
|
+
if (!isfun(funCheck)) {
|
|
160
|
+
funCheck = () => {
|
|
161
|
+
return true
|
|
162
|
+
}
|
|
163
|
+
}
|
|
162
164
|
|
|
165
|
+
//corsOrigins
|
|
166
|
+
let corsOrigins = get(opt, 'corsOrigins', [])
|
|
167
|
+
if (!isearr(corsOrigins)) {
|
|
168
|
+
corsOrigins = ['*']
|
|
169
|
+
}
|
|
163
170
|
|
|
164
|
-
//
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}, 1)
|
|
171
|
+
//delayForBasic
|
|
172
|
+
let delayForBasic = get(opt, 'delayForBasic', '')
|
|
173
|
+
if (!isp0int(delayForBasic)) {
|
|
174
|
+
delayForBasic = 0
|
|
169
175
|
}
|
|
176
|
+
delayForBasic = cint(delayForBasic)
|
|
170
177
|
|
|
178
|
+
//delayForSlice
|
|
179
|
+
let delayForSlice = get(opt, 'delayForSlice', '')
|
|
180
|
+
if (!isp0int(delayForSlice)) {
|
|
181
|
+
delayForSlice = 100
|
|
182
|
+
}
|
|
183
|
+
delayForSlice = cint(delayForSlice)
|
|
171
184
|
|
|
172
185
|
//server
|
|
173
|
-
let server
|
|
174
|
-
if (opt
|
|
186
|
+
let server = null
|
|
187
|
+
if (get(opt, 'serverHapi')) {
|
|
175
188
|
|
|
176
189
|
//use serverHapi
|
|
177
190
|
server = opt.serverHapi
|
|
@@ -181,107 +194,35 @@ function WConverhpServer(opt = {}) {
|
|
|
181
194
|
|
|
182
195
|
//create server
|
|
183
196
|
server = Hapi.server({
|
|
184
|
-
port
|
|
197
|
+
port,
|
|
185
198
|
//host: 'localhost',
|
|
186
199
|
routes: {
|
|
187
|
-
// cors: true,
|
|
188
200
|
cors: {
|
|
189
|
-
origin:
|
|
190
|
-
|
|
191
|
-
}
|
|
201
|
+
origin: corsOrigins, //Access-Control-Allow-Origin
|
|
202
|
+
credentials: false, //Access-Control-Allow-Credentials
|
|
203
|
+
},
|
|
192
204
|
},
|
|
193
205
|
})
|
|
194
206
|
|
|
195
207
|
}
|
|
196
208
|
|
|
209
|
+
//ee
|
|
210
|
+
let ee = evem() //new events.EventEmitter()
|
|
197
211
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
* wo.on('open', function() {
|
|
204
|
-
* ...
|
|
205
|
-
* })
|
|
206
|
-
*/
|
|
207
|
-
function onOpen() {} onOpen()
|
|
208
|
-
function open() {
|
|
209
|
-
eeEmit('open')
|
|
210
|
-
}
|
|
211
|
-
open()
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Hapi監聽錯誤事件
|
|
216
|
-
*
|
|
217
|
-
* @memberof WConverhpServer
|
|
218
|
-
* @param {*} err 傳入錯誤訊息
|
|
219
|
-
* @example
|
|
220
|
-
* wo.on('error', function(err) {
|
|
221
|
-
* ...
|
|
222
|
-
* })
|
|
223
|
-
*/
|
|
224
|
-
function onError() {} onError()
|
|
225
|
-
function error(msg, err) {
|
|
226
|
-
eeEmit('error', { msg, err })
|
|
212
|
+
//eeEmit
|
|
213
|
+
function eeEmit(name, ...args) {
|
|
214
|
+
setTimeout(() => {
|
|
215
|
+
ee.emit(name, ...args)
|
|
216
|
+
}, 1)
|
|
227
217
|
}
|
|
228
218
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
* Hapi監聽客戶端上線事件
|
|
232
|
-
*
|
|
233
|
-
* @memberof WConverhpServer
|
|
234
|
-
* @param {String} clientId 識別用使用者主鍵
|
|
235
|
-
* @param {*} data 使用者request訊息
|
|
236
|
-
* @example
|
|
237
|
-
* wo.on('clientEnter', function(clientId, data) {
|
|
238
|
-
* ...
|
|
239
|
-
* })
|
|
240
|
-
*/
|
|
241
|
-
function onClientEnter() {} onClientEnter()
|
|
242
|
-
/**
|
|
243
|
-
* Hapi監聽客戶端下線事件
|
|
244
|
-
*
|
|
245
|
-
* @memberof WConverhpServer
|
|
246
|
-
* @example
|
|
247
|
-
* wo.on('clientLeave', function(clientId, data) {
|
|
248
|
-
* ...
|
|
249
|
-
* })
|
|
250
|
-
*/
|
|
251
|
-
function onClientLeave() {} onClientLeave()
|
|
252
|
-
/**
|
|
253
|
-
* Hapi監聽客戶端變更(上下線)事件
|
|
254
|
-
*
|
|
255
|
-
* @memberof WConverhpServer
|
|
256
|
-
* @example
|
|
257
|
-
* wo.on('clientChange', function(num) {
|
|
258
|
-
* ...
|
|
259
|
-
* })
|
|
260
|
-
*/
|
|
261
|
-
function onClientChange() {} onClientChange()
|
|
262
|
-
ea.on('message', function({ eventName, key, data, now }) {
|
|
263
|
-
//console.log({ eventName, key, data, now })
|
|
264
|
-
if (eventName === 'enter') {
|
|
265
|
-
eeEmit('clientEnter', key, data)
|
|
266
|
-
}
|
|
267
|
-
else if (eventName === 'leave') {
|
|
268
|
-
eeEmit('clientLeave', key, data)
|
|
269
|
-
}
|
|
270
|
-
eeEmit('clientChange', now)
|
|
271
|
-
})
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
//dealData
|
|
275
|
-
async function dealData(data) {
|
|
276
|
-
//console.log('dealData', data)
|
|
219
|
+
//procDeal
|
|
220
|
+
async function procDeal(data) {
|
|
277
221
|
|
|
278
222
|
//pm, pmm
|
|
279
223
|
let pm = genPm()
|
|
280
224
|
let pmm = genPm()
|
|
281
225
|
|
|
282
|
-
//_mode
|
|
283
|
-
let _mode = get(data, '_mode', '')
|
|
284
|
-
|
|
285
226
|
//重新處理回傳結果
|
|
286
227
|
pmm
|
|
287
228
|
.then((output) => {
|
|
@@ -292,16 +233,13 @@ function WConverhpServer(opt = {}) {
|
|
|
292
233
|
//delete input, 因input可能很大故回傳數據不包含原input
|
|
293
234
|
delete data['input']
|
|
294
235
|
|
|
295
|
-
//resolve
|
|
296
236
|
pm.resolve(data)
|
|
297
|
-
|
|
298
237
|
})
|
|
299
238
|
.catch((err) => {
|
|
300
239
|
pm.reject(err)
|
|
301
240
|
})
|
|
302
241
|
|
|
303
|
-
|
|
304
|
-
if (_mode === 'execute') {
|
|
242
|
+
if (true) {
|
|
305
243
|
|
|
306
244
|
//func
|
|
307
245
|
let func = get(data, 'func', '')
|
|
@@ -313,291 +251,550 @@ function WConverhpServer(opt = {}) {
|
|
|
313
251
|
eeEmit('execute', func, input, pmm)
|
|
314
252
|
|
|
315
253
|
}
|
|
316
|
-
else if (_mode === 'broadcast') {
|
|
317
|
-
|
|
318
|
-
//input
|
|
319
|
-
let input = get(data, 'input', null)
|
|
320
|
-
|
|
321
|
-
//broadcast 廣播
|
|
322
|
-
eeEmit('broadcast', input)
|
|
323
|
-
|
|
324
|
-
//resolve
|
|
325
|
-
pmm.resolve('ok')
|
|
326
|
-
|
|
327
|
-
}
|
|
328
|
-
else if (_mode === 'deliver') {
|
|
329
254
|
|
|
330
|
-
|
|
331
|
-
|
|
255
|
+
return pm
|
|
256
|
+
}
|
|
332
257
|
|
|
333
|
-
|
|
334
|
-
|
|
258
|
+
//procUpload
|
|
259
|
+
async function procUpload(input) {
|
|
260
|
+
//console.log('procUpload', data)
|
|
335
261
|
|
|
336
|
-
|
|
337
|
-
|
|
262
|
+
//pm, pmm
|
|
263
|
+
let pm = genPm()
|
|
264
|
+
let pmm = genPm()
|
|
338
265
|
|
|
339
|
-
|
|
340
|
-
|
|
266
|
+
//重新處理回傳結果
|
|
267
|
+
pmm
|
|
268
|
+
.then((output) => {
|
|
341
269
|
|
|
342
|
-
|
|
343
|
-
|
|
270
|
+
//resolve
|
|
271
|
+
pm.resolve(output)
|
|
344
272
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
273
|
+
})
|
|
274
|
+
.catch((err) => {
|
|
275
|
+
pm.reject(err)
|
|
276
|
+
})
|
|
348
277
|
|
|
349
|
-
|
|
350
|
-
broadcastMessages[clientId] = []
|
|
278
|
+
if (true) {
|
|
351
279
|
|
|
352
|
-
//
|
|
353
|
-
pmm
|
|
280
|
+
//upload 上傳檔案
|
|
281
|
+
eeEmit('upload', input, pmm)
|
|
354
282
|
|
|
355
283
|
}
|
|
356
|
-
else {
|
|
357
|
-
let msg = 'can not find _mode in data'
|
|
358
|
-
error(msg, data)
|
|
359
|
-
pm.reject(msg)
|
|
360
|
-
pmm.reject()
|
|
361
|
-
}
|
|
362
284
|
|
|
363
285
|
return pm
|
|
364
286
|
}
|
|
365
287
|
|
|
288
|
+
//responseU8aStream
|
|
289
|
+
function responseU8aStream(res, u8a) {
|
|
290
|
+
|
|
291
|
+
//stream
|
|
292
|
+
let smr = new stream.Readable()
|
|
293
|
+
smr._read = () => {}
|
|
294
|
+
smr.push(u8a)
|
|
295
|
+
smr.push(null)
|
|
296
|
+
|
|
297
|
+
return res.response(smr)
|
|
298
|
+
.header('Cache-Control', 'no-cache, no-store, must-revalidate')
|
|
299
|
+
.header('Content-Type', 'application/octet-stream')
|
|
300
|
+
.header('Content-Length', smr.readableLength)
|
|
301
|
+
}
|
|
366
302
|
|
|
367
303
|
//apiMain
|
|
368
304
|
let apiMain = {
|
|
369
|
-
path:
|
|
305
|
+
path: `/${apiName}`,
|
|
370
306
|
method: 'POST',
|
|
371
|
-
// config: {
|
|
372
|
-
// payload: {
|
|
373
|
-
// output: 'stream',
|
|
374
|
-
// maxBytes: 1024 * 1024 * 1024, //1g
|
|
375
|
-
// },
|
|
376
|
-
// },
|
|
377
307
|
options: {
|
|
378
308
|
payload: {
|
|
379
|
-
maxBytes: 1024 * 1024 * 1024,
|
|
380
|
-
|
|
381
|
-
|
|
309
|
+
maxBytes: 1024 * 1024 * 1024 * 1024, //預設為1mb, 調整至1tb, 也就是給予3次方
|
|
310
|
+
maxParts: 1000 * 1000 * 1000, //預設為1000, 給予3次方
|
|
311
|
+
timeout: false, //避免請求未完成時中斷
|
|
312
|
+
output: 'stream',
|
|
313
|
+
parse: false,
|
|
382
314
|
},
|
|
383
315
|
timeout: {
|
|
384
|
-
socket:
|
|
316
|
+
socket: false, //避免socket自動關閉
|
|
317
|
+
server: false,
|
|
385
318
|
},
|
|
386
319
|
},
|
|
387
320
|
handler: async function (req, res) {
|
|
388
|
-
//console.log(req, res)
|
|
389
|
-
//console.log('payload', req.payload)
|
|
321
|
+
// console.log(req, res)
|
|
322
|
+
// console.log('payload', req.payload)
|
|
390
323
|
|
|
391
|
-
|
|
324
|
+
//headers
|
|
392
325
|
let headers = get(req, 'headers')
|
|
393
326
|
headers = iseobj(headers) ? headers : ''
|
|
327
|
+
// console.log('headers', headers)
|
|
328
|
+
|
|
329
|
+
//query
|
|
394
330
|
let query = get(req, 'query')
|
|
395
331
|
query = iseobj(query) ? query : ''
|
|
332
|
+
// console.log('query', query)
|
|
333
|
+
|
|
334
|
+
//token
|
|
335
|
+
let token = get(query, 'token', '')
|
|
336
|
+
|
|
337
|
+
//check
|
|
338
|
+
if (true) {
|
|
339
|
+
|
|
340
|
+
//funCheck
|
|
341
|
+
let m = funCheck({ token, headers, query })
|
|
342
|
+
if (ispm(m)) {
|
|
343
|
+
m = await m
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
//check
|
|
347
|
+
if (m !== true) {
|
|
348
|
+
return res.response({ error: 'permission denied' }).code(400)
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
//eeEmit
|
|
396
354
|
eeEmit('handler', {
|
|
355
|
+
api: 'apiMain',
|
|
397
356
|
headers,
|
|
398
357
|
query,
|
|
399
358
|
})
|
|
400
359
|
|
|
401
|
-
//
|
|
402
|
-
|
|
403
|
-
// return res.response('Internal Server Error').code(500)
|
|
404
|
-
// }
|
|
360
|
+
//receive
|
|
361
|
+
let receive = () => {
|
|
405
362
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
// console.log('bbInp', bbInp)
|
|
363
|
+
//pm
|
|
364
|
+
let pm = genPm()
|
|
409
365
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
366
|
+
//totalSize, chunks
|
|
367
|
+
// let totalSize = 0
|
|
368
|
+
let chunks = []
|
|
369
|
+
|
|
370
|
+
//smw
|
|
371
|
+
let smw = new stream.Writable({
|
|
372
|
+
write(chunk, encoding, cb) {
|
|
373
|
+
// console.log('receive payload', chunk)
|
|
374
|
+
|
|
375
|
+
// //totalSize
|
|
376
|
+
// totalSize += chunk.length
|
|
377
|
+
|
|
378
|
+
//push
|
|
379
|
+
chunks.push(chunk)
|
|
380
|
+
// console.log('chunk.length', chunk.length, 'totalSize', totalSize)
|
|
381
|
+
|
|
382
|
+
//setTimeout, 延遲觸發cb
|
|
383
|
+
setTimeout(() => {
|
|
384
|
+
cb()
|
|
385
|
+
}, delayForBasic)
|
|
386
|
+
|
|
387
|
+
}
|
|
388
|
+
})
|
|
389
|
+
|
|
390
|
+
//pipe
|
|
391
|
+
req.payload.pipe(smw)
|
|
392
|
+
|
|
393
|
+
//end
|
|
394
|
+
req.payload.on('end', () => {
|
|
395
|
+
// console.log(`receive payload done`)
|
|
396
|
+
|
|
397
|
+
//concat
|
|
398
|
+
let fileBuffer = Buffer.concat(chunks)
|
|
399
|
+
// console.log('fileBuffer', fileBuffer, fileBuffer.length)
|
|
400
|
+
|
|
401
|
+
//clear, 釋放記憶體
|
|
402
|
+
chunks = []
|
|
403
|
+
|
|
404
|
+
//resolve
|
|
405
|
+
pm.resolve(fileBuffer)
|
|
406
|
+
|
|
407
|
+
})
|
|
408
|
+
|
|
409
|
+
//error
|
|
410
|
+
req.payload.on('error', (err) => {
|
|
411
|
+
console.log(`receive payload err`, err)
|
|
412
|
+
// pm.reject(res.response({ error: err.message }).code(500))
|
|
413
|
+
pm.reject(err.message)
|
|
414
|
+
})
|
|
415
|
+
|
|
416
|
+
return pm
|
|
414
417
|
}
|
|
415
418
|
|
|
419
|
+
//receive
|
|
420
|
+
let bbInp = await receive()
|
|
421
|
+
// console.log('bbInp', bbInp)
|
|
422
|
+
|
|
416
423
|
//u8aInp
|
|
417
424
|
let u8aInp = new Uint8Array(bbInp)
|
|
418
|
-
//console.log('u8aInp', u8aInp)
|
|
425
|
+
// console.log('u8aInp', u8aInp)
|
|
419
426
|
|
|
420
427
|
//u8arr2obj
|
|
421
428
|
let inp = u8arr2obj(u8aInp)
|
|
422
|
-
//console.log('inp', inp)
|
|
429
|
+
// console.log('inp', inp)
|
|
423
430
|
|
|
424
|
-
//
|
|
425
|
-
let
|
|
431
|
+
//procDeal
|
|
432
|
+
let out = {}
|
|
433
|
+
await procDeal(inp)
|
|
434
|
+
.then(function(msg) {
|
|
435
|
+
out.success = msg
|
|
436
|
+
})
|
|
437
|
+
.catch(function(msg) {
|
|
438
|
+
out.error = msg
|
|
439
|
+
})
|
|
440
|
+
// console.log('out', out)
|
|
441
|
+
|
|
442
|
+
//u8aOut
|
|
443
|
+
let u8aOut = obj2u8arr(out)
|
|
444
|
+
// console.log('u8aOut', u8aOut)
|
|
445
|
+
|
|
446
|
+
return responseU8aStream(res, u8aOut)
|
|
447
|
+
},
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
//apiSlice
|
|
451
|
+
let apiSlice = {
|
|
452
|
+
path: `/${apiSliceName}`,
|
|
453
|
+
method: 'POST',
|
|
454
|
+
options: {
|
|
455
|
+
payload: {
|
|
456
|
+
maxBytes: 1024 * 1024 * 1024 * 1024, //預設為1mb, 調整至1tb, 也就是給予3次方
|
|
457
|
+
maxParts: 1000 * 1000 * 1000, //預設為1000, 給予3次方
|
|
458
|
+
timeout: false, //避免請求未完成時中斷
|
|
459
|
+
output: 'stream',
|
|
460
|
+
parse: false,
|
|
461
|
+
},
|
|
462
|
+
timeout: {
|
|
463
|
+
socket: false, //避免socket自動關閉
|
|
464
|
+
server: false,
|
|
465
|
+
},
|
|
466
|
+
},
|
|
467
|
+
handler: async function (req, res) {
|
|
468
|
+
// console.log(req, res)
|
|
469
|
+
// console.log('payload', req.payload)
|
|
470
|
+
|
|
471
|
+
//headers
|
|
472
|
+
let headers = get(req, 'headers')
|
|
473
|
+
headers = iseobj(headers) ? headers : ''
|
|
474
|
+
// console.log('headers', headers)
|
|
475
|
+
|
|
476
|
+
//query
|
|
477
|
+
let query = get(req, 'query')
|
|
478
|
+
query = iseobj(query) ? query : ''
|
|
479
|
+
// console.log('query', query)
|
|
480
|
+
|
|
481
|
+
//token
|
|
482
|
+
let token = get(query, 'token', '')
|
|
483
|
+
|
|
484
|
+
//check
|
|
485
|
+
if (true) {
|
|
486
|
+
|
|
487
|
+
//funCheck
|
|
488
|
+
let m = funCheck({ token, headers, query })
|
|
489
|
+
if (ispm(m)) {
|
|
490
|
+
m = await m
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
//check
|
|
494
|
+
if (m !== true) {
|
|
495
|
+
return res.response({ error: 'permission denied' }).code(400)
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
}
|
|
426
499
|
|
|
427
|
-
//
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
500
|
+
//eeEmit
|
|
501
|
+
eeEmit('handler', {
|
|
502
|
+
api: 'apiSlice',
|
|
503
|
+
headers,
|
|
504
|
+
query,
|
|
505
|
+
})
|
|
506
|
+
|
|
507
|
+
//chunkIndex, chunkTotal, packageId, 從headers接收
|
|
508
|
+
let chunkIndex = get(headers, 'chunk-index', '')
|
|
509
|
+
let chunkTotal = get(headers, 'chunk-total', '')
|
|
510
|
+
let packageId = get(headers, 'package-id', '')
|
|
511
|
+
|
|
512
|
+
//check
|
|
513
|
+
if (!isp0int(chunkIndex)) {
|
|
514
|
+
console.log('invalid chunkIndex in headers')
|
|
515
|
+
return res.response({ error: 'invalid chunkIndex in headers' }).code(400)
|
|
516
|
+
}
|
|
517
|
+
chunkIndex = cint(chunkIndex)
|
|
518
|
+
if (!isp0int(chunkTotal)) {
|
|
519
|
+
console.log('invalid chunkTotal in headers')
|
|
520
|
+
return res.response({ error: 'invalid chunkTotal in headers' }).code(400)
|
|
431
521
|
}
|
|
522
|
+
chunkTotal = cint(chunkTotal)
|
|
523
|
+
if (!isestr(packageId)) {
|
|
524
|
+
console.log('invalid packageId in headers')
|
|
525
|
+
return res.response({ error: 'invalid packageId in headers' }).code(400)
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
//pathFileChunk
|
|
529
|
+
let pathFileChunk = `${pathUploadTemp}/${packageId}_${chunkIndex}` //path.join(pathUploadTemp, `${packageId}_${chunkIndex}`)
|
|
530
|
+
// console.log('pathFileChunk', pathFileChunk)
|
|
531
|
+
|
|
532
|
+
//fileStream
|
|
533
|
+
let fileStream = fs.createWriteStream(pathFileChunk)
|
|
534
|
+
|
|
535
|
+
//receive
|
|
536
|
+
let receive = () => {
|
|
432
537
|
|
|
433
|
-
|
|
434
|
-
|
|
538
|
+
//pm
|
|
539
|
+
let pm = genPm()
|
|
435
540
|
|
|
436
|
-
|
|
541
|
+
//pipe
|
|
542
|
+
req.payload.pipe(fileStream)
|
|
543
|
+
// console.log(`receiving chunk[${chunkIndex + 1}/${chunkTotal}]...`)
|
|
544
|
+
|
|
545
|
+
//end
|
|
546
|
+
req.payload.on('end', () => {
|
|
547
|
+
// console.log(`receive chunk[${chunkIndex + 1}/${chunkTotal}] done`)
|
|
548
|
+
|
|
549
|
+
//setTimeout, 切片上傳添加延遲處理, 避免佔滿伺服器CPU與流量
|
|
550
|
+
setTimeout(() => {
|
|
551
|
+
pm.resolve(`chunk[${chunkIndex}/${chunkTotal}] of packageId[${packageId}] done`)
|
|
552
|
+
}, delayForSlice)
|
|
553
|
+
|
|
554
|
+
})
|
|
555
|
+
|
|
556
|
+
//error
|
|
557
|
+
req.payload.on('error', (err) => {
|
|
558
|
+
console.log(`receive chunk[${chunkIndex + 1}/${chunkTotal}] err`, err)
|
|
559
|
+
pm.reject(`chunk[${chunkIndex}/${chunkTotal}] of packageId[${packageId}] err`)
|
|
560
|
+
})
|
|
561
|
+
|
|
562
|
+
return pm
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
//receive
|
|
437
566
|
let out = {}
|
|
438
|
-
await
|
|
567
|
+
await receive()
|
|
439
568
|
.then(function(msg) {
|
|
440
569
|
out.success = msg
|
|
441
570
|
})
|
|
442
571
|
.catch(function(msg) {
|
|
443
572
|
out.error = msg
|
|
444
573
|
})
|
|
574
|
+
// console.log('out', out)
|
|
445
575
|
|
|
446
576
|
//u8aOut
|
|
447
577
|
let u8aOut = obj2u8arr(out)
|
|
578
|
+
// console.log('u8aOut', u8aOut)
|
|
448
579
|
|
|
449
|
-
|
|
450
|
-
let sm = new stream.Readable()
|
|
451
|
-
sm._read = () => {}
|
|
452
|
-
sm.push(u8aOut)
|
|
453
|
-
sm.push(null)
|
|
454
|
-
// if (out.success._mode !== 'polling') {
|
|
455
|
-
// console.log('out', out)
|
|
456
|
-
// console.log('u8aOut', u8aOut)
|
|
457
|
-
// }
|
|
458
|
-
|
|
459
|
-
return res.response(sm)
|
|
460
|
-
.header('Cache-Control', 'no-cache, no-store, must-revalidate')
|
|
461
|
-
.header('Content-Type', 'application/octet-stream')
|
|
462
|
-
.header('Content-Length', sm.readableLength)
|
|
580
|
+
return responseU8aStream(res, u8aOut)
|
|
463
581
|
},
|
|
464
582
|
}
|
|
465
583
|
|
|
584
|
+
//apiSliceMerge
|
|
585
|
+
let apiSliceMerge = {
|
|
586
|
+
path: `/${apiSliceName}m`,
|
|
587
|
+
method: 'POST',
|
|
588
|
+
options: {
|
|
589
|
+
payload: {
|
|
590
|
+
maxBytes: 1024 * 1024 * 1024 * 1024, //預設為1mb, 調整至1tb, 也就是給予3次方
|
|
591
|
+
maxParts: 1000 * 1000 * 1000, //預設為1000, 給予3次方
|
|
592
|
+
timeout: false, //避免請求未完成時中斷
|
|
593
|
+
parse: true,
|
|
594
|
+
},
|
|
595
|
+
timeout: {
|
|
596
|
+
socket: false, //避免socket自動關閉
|
|
597
|
+
server: false,
|
|
598
|
+
},
|
|
599
|
+
},
|
|
600
|
+
handler: async function (req, res) {
|
|
601
|
+
// console.log(req, res)
|
|
602
|
+
// console.log('payload', req.payload)
|
|
466
603
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
function onBroadcast() {} onBroadcast()
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
/**
|
|
497
|
-
* Hapi監聽客戶端發送事件
|
|
498
|
-
*
|
|
499
|
-
* @memberof WConverhpServer
|
|
500
|
-
* @param {*} data 傳入發送訊息
|
|
501
|
-
* @example
|
|
502
|
-
* wo.on('deliver', function(data) {
|
|
503
|
-
* ...
|
|
504
|
-
* })
|
|
505
|
-
*/
|
|
506
|
-
function onDeliver() {} onDeliver()
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
/**
|
|
510
|
-
* Hapi通訊物件對全客戶端廣播函數
|
|
511
|
-
*
|
|
512
|
-
* @memberof WConverhpServer
|
|
513
|
-
* @function broadcast
|
|
514
|
-
* @param {*} data 輸入廣播函數之輸入資訊
|
|
515
|
-
* @param {Function} cb 輸入進度函數
|
|
516
|
-
* @example
|
|
517
|
-
* let data = {...}
|
|
518
|
-
* wo.broadcast(data, cb)
|
|
519
|
-
*/
|
|
520
|
-
ee.broadcast = function (data, cbProgress = function () {}) {
|
|
521
|
-
|
|
522
|
-
//check, broadcastMessages受ea偵測頻率1s影響, 伺服器初始化後至少需1s才會有有效對象
|
|
523
|
-
if (iser(broadcastMessages)) {
|
|
524
|
-
//console.log('no client for broadcast')
|
|
525
|
-
return
|
|
526
|
-
}
|
|
604
|
+
//headers
|
|
605
|
+
let headers = get(req, 'headers')
|
|
606
|
+
headers = iseobj(headers) ? headers : ''
|
|
607
|
+
// console.log('headers', headers)
|
|
608
|
+
|
|
609
|
+
//query
|
|
610
|
+
let query = get(req, 'query')
|
|
611
|
+
query = iseobj(query) ? query : ''
|
|
612
|
+
// console.log('query', query)
|
|
613
|
+
|
|
614
|
+
//token
|
|
615
|
+
let token = get(query, 'token', '')
|
|
616
|
+
|
|
617
|
+
//check
|
|
618
|
+
if (true) {
|
|
619
|
+
|
|
620
|
+
//funCheck
|
|
621
|
+
let m = funCheck({ token, headers, query })
|
|
622
|
+
if (ispm(m)) {
|
|
623
|
+
m = await m
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
//check
|
|
627
|
+
if (m !== true) {
|
|
628
|
+
return res.response({ error: 'permission denied' }).code(400)
|
|
629
|
+
}
|
|
527
630
|
|
|
528
|
-
|
|
529
|
-
let t = {}
|
|
530
|
-
each(broadcastMessages, (v, k) => {
|
|
631
|
+
}
|
|
531
632
|
|
|
532
|
-
//
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
633
|
+
//eeEmit
|
|
634
|
+
eeEmit('handler', {
|
|
635
|
+
api: 'apiSliceMerge',
|
|
636
|
+
headers,
|
|
637
|
+
query,
|
|
536
638
|
})
|
|
537
639
|
|
|
538
|
-
//
|
|
539
|
-
|
|
640
|
+
//filename, chunkTotal, packageId, 從payload接收
|
|
641
|
+
let filename = get(req, 'payload.filename', '')
|
|
642
|
+
let chunkTotal = get(req, 'payload.chunk-total', '')
|
|
643
|
+
let packageId = get(req, 'payload.package-id', '')
|
|
540
644
|
|
|
541
|
-
|
|
542
|
-
|
|
645
|
+
//check
|
|
646
|
+
if (!isestr(filename)) {
|
|
647
|
+
console.log('invalid filename in payload')
|
|
648
|
+
return res.response({ error: 'invalid filename in payload' }).code(400)
|
|
649
|
+
}
|
|
650
|
+
if (!isp0int(chunkTotal)) {
|
|
651
|
+
console.log('invalid chunkTotal in payload')
|
|
652
|
+
return res.response({ error: 'invalid chunkTotal in payload' }).code(400)
|
|
653
|
+
}
|
|
654
|
+
chunkTotal = cint(chunkTotal)
|
|
655
|
+
if (!isestr(packageId)) {
|
|
656
|
+
console.log('invalid packageId in payload')
|
|
657
|
+
return res.response({ error: 'invalid packageId in payload' }).code(400)
|
|
658
|
+
}
|
|
543
659
|
|
|
544
|
-
|
|
545
|
-
|
|
660
|
+
//merge
|
|
661
|
+
let merge = async () => {
|
|
662
|
+
let errTemp = ''
|
|
546
663
|
|
|
547
|
-
|
|
664
|
+
//pathFileMerge
|
|
665
|
+
let pathFileMerge = path.join(pathUploadTemp, `${packageId}`)
|
|
666
|
+
// console.log('pathFileMerge', pathFileMerge)
|
|
548
667
|
|
|
668
|
+
//fileStream
|
|
669
|
+
let fileStream = fs.createWriteStream(pathFileMerge)
|
|
670
|
+
// console.log(`merge filename[${filename}] start`)
|
|
549
671
|
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
* @function deliver
|
|
555
|
-
* @param {String} clientId 輸入識別用使用者主鍵字串
|
|
556
|
-
* @param {*} data 輸入發送函數之輸入資訊
|
|
557
|
-
* @param {Function} cb 輸入進度函數
|
|
558
|
-
* @example
|
|
559
|
-
* let clientId = '...'
|
|
560
|
-
* let data = {...}
|
|
561
|
-
* wo.deliver(clientId, data, cb)
|
|
562
|
-
*/
|
|
563
|
-
ee.deliver = function (clientId, data, cbProgress = function () {}) {
|
|
564
|
-
|
|
565
|
-
//bms, 此時有可能ea trigger為非同步, 尚未把
|
|
566
|
-
let bms = get(broadcastMessages, clientId, [])
|
|
567
|
-
|
|
568
|
-
//push
|
|
569
|
-
bms.push({
|
|
570
|
-
mode: 'deliver',
|
|
571
|
-
data,
|
|
572
|
-
})
|
|
672
|
+
//使用try catch攔截,使stream能完整創造與結束
|
|
673
|
+
try {
|
|
674
|
+
for (let i = 0; i < chunkTotal; i++) {
|
|
675
|
+
// console.log(`merge ${i + 1}/${chunkTotal}`)
|
|
573
676
|
|
|
574
|
-
|
|
575
|
-
|
|
677
|
+
//chunkIndex
|
|
678
|
+
let chunkIndex = i
|
|
576
679
|
|
|
577
|
-
|
|
578
|
-
|
|
680
|
+
//pathFileChunk
|
|
681
|
+
let pathFileChunk = path.join(pathUploadTemp, `${packageId}_${chunkIndex}`)
|
|
579
682
|
|
|
580
|
-
|
|
683
|
+
//check
|
|
684
|
+
if (!fsIsFile(pathFileChunk)) {
|
|
685
|
+
// console.log(`pathFileChunk[${pathFileChunk}] is not a file`)
|
|
686
|
+
// return res.response({ error: `Missing chunk ${i} of filename[${filename}]` }).code(400)
|
|
687
|
+
throw new Error(`Missing chunk ${i} of filename[${filename}]`)
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
// console.log(`merging chunk[${chunkIndex + 1}/${chunkTotal}]...`)
|
|
581
691
|
|
|
692
|
+
//chunkData
|
|
693
|
+
let chunkData = fs.readFileSync(pathFileChunk)
|
|
582
694
|
|
|
695
|
+
//write
|
|
696
|
+
fileStream.write(chunkData)
|
|
697
|
+
|
|
698
|
+
//fsDeleteFile
|
|
699
|
+
fsDeleteFile(pathFileChunk)
|
|
700
|
+
|
|
701
|
+
// console.log(`merge chunk[${chunkIndex + 1}/${chunkTotal}] done`)
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
catch (err) {
|
|
705
|
+
errTemp = err.message
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
//end
|
|
709
|
+
fileStream.end()
|
|
710
|
+
// console.log(`merge filename[${filename}] done`)
|
|
711
|
+
|
|
712
|
+
//check
|
|
713
|
+
if (isestr(errTemp)) {
|
|
714
|
+
return Promise.reject(errTemp)
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
//r
|
|
718
|
+
let r = {
|
|
719
|
+
// message: `Merged filename[${filename}] successfully`,
|
|
720
|
+
filename,
|
|
721
|
+
path: pathFileMerge,
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
return r
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
//core
|
|
728
|
+
let core = async() => {
|
|
729
|
+
|
|
730
|
+
//merge
|
|
731
|
+
// console.log('merge start')
|
|
732
|
+
let r = await merge()
|
|
733
|
+
// console.log('merge done', r)
|
|
734
|
+
|
|
735
|
+
//procUpload
|
|
736
|
+
// console.log('procUpload start')
|
|
737
|
+
let rr = await procUpload(r)
|
|
738
|
+
// console.log('procUpload done', rr)
|
|
739
|
+
|
|
740
|
+
return rr
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
//core
|
|
744
|
+
let out = {}
|
|
745
|
+
await core()
|
|
746
|
+
.then(function(msg) {
|
|
747
|
+
out.success = msg
|
|
748
|
+
})
|
|
749
|
+
.catch(function(msg) {
|
|
750
|
+
out.error = msg
|
|
751
|
+
})
|
|
752
|
+
// console.log('out', out)
|
|
753
|
+
|
|
754
|
+
//u8aOut
|
|
755
|
+
let u8aOut = obj2u8arr(out)
|
|
756
|
+
// console.log('u8aOut', u8aOut)
|
|
757
|
+
|
|
758
|
+
return responseU8aStream(res, u8aOut)
|
|
759
|
+
},
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
//startServer
|
|
583
763
|
async function startServer() {
|
|
584
764
|
|
|
585
765
|
//register inert
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
}
|
|
596
|
-
|
|
766
|
+
if (useInert) {
|
|
767
|
+
await server.register(Inert)
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
//apiRoutes
|
|
771
|
+
let apiRoutes = []
|
|
772
|
+
if (useInert) {
|
|
773
|
+
let api = {
|
|
774
|
+
method: 'GET',
|
|
775
|
+
path: '/{file*}',
|
|
776
|
+
handler: {
|
|
777
|
+
directory: {
|
|
778
|
+
path: `${pathStaticFiles}/`
|
|
779
|
+
}
|
|
780
|
+
},
|
|
781
|
+
}
|
|
782
|
+
apiRoutes = [
|
|
783
|
+
...apiRoutes,
|
|
784
|
+
api,
|
|
785
|
+
]
|
|
786
|
+
}
|
|
787
|
+
if (true) {
|
|
788
|
+
apiRoutes = [
|
|
789
|
+
...apiRoutes,
|
|
790
|
+
apiMain,
|
|
791
|
+
apiSlice,
|
|
792
|
+
apiSliceMerge,
|
|
793
|
+
]
|
|
597
794
|
}
|
|
598
795
|
|
|
599
796
|
//route
|
|
600
|
-
server.route(
|
|
797
|
+
server.route(apiRoutes)
|
|
601
798
|
|
|
602
799
|
//start
|
|
603
800
|
await server.start()
|
|
@@ -606,8 +803,9 @@ function WConverhpServer(opt = {}) {
|
|
|
606
803
|
|
|
607
804
|
}
|
|
608
805
|
|
|
609
|
-
|
|
610
|
-
|
|
806
|
+
//start
|
|
807
|
+
if (get(opt, 'serverHapi')) {
|
|
808
|
+
opt.serverHapi.route([apiMain, apiSlice, apiSliceMerge])
|
|
611
809
|
}
|
|
612
810
|
else {
|
|
613
811
|
startServer()
|