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