w-converhp 2.0.10 → 2.0.11
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/README.md +66 -1
- 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 +3 -3
- package/docs/WConverhpClient.mjs.html +163 -5
- package/docs/WConverhpServer.html +3 -3
- package/docs/WConverhpServer.mjs.html +258 -71
- package/docs/index.html +1 -1
- package/package.json +3 -3
- package/sclc.mjs +4 -2
- package/scld.mjs +54 -0
- package/src/WConverhpClient.mjs +161 -3
- package/src/WConverhpServer.mjs +257 -70
- package/src/mergeFiles.mjs +16 -105
- package/src/mergeFiles.wk.umd.js +1 -1
- package/srv.mjs +39 -1
- package/test/1mb.7z +0 -0
- package/test/downloadLargeFile.test.mjs +166 -0
- package/test/executeWithFile.test.mjs +1 -1
- package/test/uploadLargeFile.test.mjs +5 -5
- package/web.html +28 -1
package/src/WConverhpServer.mjs
CHANGED
|
@@ -4,6 +4,7 @@ import Hapi from '@hapi/hapi'
|
|
|
4
4
|
import Inert from '@hapi/inert' //提供靜態檔案
|
|
5
5
|
import get from 'lodash-es/get.js'
|
|
6
6
|
import genPm from 'wsemi/src/genPm.mjs'
|
|
7
|
+
import evem from 'wsemi/src/evem.mjs'
|
|
7
8
|
import iseobj from 'wsemi/src/iseobj.mjs'
|
|
8
9
|
import isestr from 'wsemi/src/isestr.mjs'
|
|
9
10
|
import isp0int from 'wsemi/src/isp0int.mjs'
|
|
@@ -11,9 +12,10 @@ import ispint from 'wsemi/src/ispint.mjs'
|
|
|
11
12
|
import isearr from 'wsemi/src/isearr.mjs'
|
|
12
13
|
import isbol from 'wsemi/src/isbol.mjs'
|
|
13
14
|
import isfun from 'wsemi/src/isfun.mjs'
|
|
15
|
+
import isnum from 'wsemi/src/isnum.mjs'
|
|
14
16
|
import ispm from 'wsemi/src/ispm.mjs'
|
|
15
17
|
import cint from 'wsemi/src/cint.mjs'
|
|
16
|
-
import
|
|
18
|
+
import haskey from 'wsemi/src/haskey.mjs'
|
|
17
19
|
import obj2u8arr from 'wsemi/src/obj2u8arr.mjs'
|
|
18
20
|
import u8arr2obj from 'wsemi/src/u8arr2obj.mjs'
|
|
19
21
|
import fsIsFolder from 'wsemi/src/fsIsFolder.mjs'
|
|
@@ -110,6 +112,44 @@ import mergeFiles from './mergeFiles.wk.umd.js'
|
|
|
110
112
|
* }
|
|
111
113
|
*
|
|
112
114
|
* })
|
|
115
|
+
* wo.on('download', (input, pm) => {
|
|
116
|
+
* console.log(`Server[port:${opt.port}]: download`, input)
|
|
117
|
+
*
|
|
118
|
+
* try {
|
|
119
|
+
* ms.push({ 'download': input })
|
|
120
|
+
*
|
|
121
|
+
* //fp
|
|
122
|
+
* let fp = `./test/1mb.7z`
|
|
123
|
+
*
|
|
124
|
+
* //streamRead
|
|
125
|
+
* let streamRead = fs.createReadStream(fp)
|
|
126
|
+
*
|
|
127
|
+
* //fileName
|
|
128
|
+
* let fileName = `1mb.7z`
|
|
129
|
+
*
|
|
130
|
+
* //fileSize
|
|
131
|
+
* let stats = fs.statSync(fp)
|
|
132
|
+
* let fileSize = stats.size
|
|
133
|
+
*
|
|
134
|
+
* //fileType
|
|
135
|
+
* let fileType = 'application/x-7z-compressed'
|
|
136
|
+
*
|
|
137
|
+
* //output
|
|
138
|
+
* let output = {
|
|
139
|
+
* streamRead,
|
|
140
|
+
* fileName,
|
|
141
|
+
* fileSize,
|
|
142
|
+
* fileType,
|
|
143
|
+
* }
|
|
144
|
+
*
|
|
145
|
+
* pm.resolve(output)
|
|
146
|
+
* }
|
|
147
|
+
* catch (err) {
|
|
148
|
+
* console.log('download error', err)
|
|
149
|
+
* pm.reject('download error')
|
|
150
|
+
* }
|
|
151
|
+
*
|
|
152
|
+
* })
|
|
113
153
|
* wo.on('handler', (data) => {
|
|
114
154
|
* // console.log(`Server[port:${opt.port}]: handler`, data)
|
|
115
155
|
* })
|
|
@@ -141,8 +181,11 @@ function WConverhpServer(opt = {}) {
|
|
|
141
181
|
apiName = 'api'
|
|
142
182
|
}
|
|
143
183
|
|
|
144
|
-
//
|
|
145
|
-
let
|
|
184
|
+
//apiUploadSliceName
|
|
185
|
+
let apiUploadSliceName = `${apiName}slc`
|
|
186
|
+
|
|
187
|
+
//apiDownloadName
|
|
188
|
+
let apiDownloadName = `${apiName}dw`
|
|
146
189
|
|
|
147
190
|
//pathUploadTemp
|
|
148
191
|
let pathUploadTemp = get(opt, 'pathUploadTemp')
|
|
@@ -260,7 +303,7 @@ function WConverhpServer(opt = {}) {
|
|
|
260
303
|
|
|
261
304
|
//procUpload
|
|
262
305
|
async function procUpload(input) {
|
|
263
|
-
//console.log('procUpload',
|
|
306
|
+
//console.log('procUpload', input)
|
|
264
307
|
|
|
265
308
|
//pm, pmm
|
|
266
309
|
let pm = genPm()
|
|
@@ -280,7 +323,7 @@ function WConverhpServer(opt = {}) {
|
|
|
280
323
|
|
|
281
324
|
if (true) {
|
|
282
325
|
|
|
283
|
-
//upload 上傳檔案
|
|
326
|
+
//upload, 上傳檔案
|
|
284
327
|
eeEmit('upload', input, pmm)
|
|
285
328
|
|
|
286
329
|
}
|
|
@@ -288,8 +331,38 @@ function WConverhpServer(opt = {}) {
|
|
|
288
331
|
return pm
|
|
289
332
|
}
|
|
290
333
|
|
|
334
|
+
//procDownload
|
|
335
|
+
async function procDownload(input) {
|
|
336
|
+
// console.log('procDownload', input)
|
|
337
|
+
|
|
338
|
+
//pm, pmm
|
|
339
|
+
let pm = genPm()
|
|
340
|
+
let pmm = genPm()
|
|
341
|
+
|
|
342
|
+
//重新處理回傳結果
|
|
343
|
+
pmm
|
|
344
|
+
.then((output) => {
|
|
345
|
+
|
|
346
|
+
//resolve
|
|
347
|
+
pm.resolve(output)
|
|
348
|
+
|
|
349
|
+
})
|
|
350
|
+
.catch((err) => {
|
|
351
|
+
pm.reject(err)
|
|
352
|
+
})
|
|
353
|
+
|
|
354
|
+
if (true) {
|
|
355
|
+
|
|
356
|
+
//download, 下載檔案
|
|
357
|
+
eeEmit('download', input, pmm)
|
|
358
|
+
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
return pm
|
|
362
|
+
}
|
|
363
|
+
|
|
291
364
|
//responseU8aStream
|
|
292
|
-
function responseU8aStream(res, u8a) {
|
|
365
|
+
function responseU8aStream(res, u8a, opt = {}) {
|
|
293
366
|
|
|
294
367
|
//stream
|
|
295
368
|
let smr = new stream.Readable()
|
|
@@ -297,12 +370,32 @@ function WConverhpServer(opt = {}) {
|
|
|
297
370
|
smr.push(u8a)
|
|
298
371
|
smr.push(null)
|
|
299
372
|
|
|
373
|
+
//returnType
|
|
374
|
+
let returnType = get(opt, 'returnType', '')
|
|
375
|
+
|
|
376
|
+
//returnMsg
|
|
377
|
+
let returnMsg = get(opt, 'returnMsg', '')
|
|
378
|
+
|
|
300
379
|
return res.response(smr)
|
|
380
|
+
.header('Return-Type', returnType)
|
|
381
|
+
.header('Return-Msg', returnMsg)
|
|
301
382
|
.header('Cache-Control', 'no-cache, no-store, must-revalidate')
|
|
302
383
|
.header('Content-Type', 'application/octet-stream')
|
|
303
384
|
.header('Content-Length', smr.readableLength)
|
|
304
385
|
}
|
|
305
386
|
|
|
387
|
+
//responseU8aStreamWithError
|
|
388
|
+
function responseU8aStreamWithError(res, msg) {
|
|
389
|
+
|
|
390
|
+
//u8aOut
|
|
391
|
+
let u8aOut = obj2u8arr({
|
|
392
|
+
error: msg,
|
|
393
|
+
})
|
|
394
|
+
// console.log('download u8aOut', u8aOut)
|
|
395
|
+
|
|
396
|
+
return responseU8aStream(res, u8aOut, { returnType: 'error', returnMsg: msg })
|
|
397
|
+
}
|
|
398
|
+
|
|
306
399
|
//apiMain
|
|
307
400
|
let apiMain = {
|
|
308
401
|
path: `/${apiName}`,
|
|
@@ -312,7 +405,7 @@ function WConverhpServer(opt = {}) {
|
|
|
312
405
|
maxBytes: 1024 * 1024 * 1024 * 1024, //預設為1mb, 調整至1tb, 也就是給予3次方
|
|
313
406
|
maxParts: 1000 * 1000 * 1000, //預設為1000, 給予3次方
|
|
314
407
|
timeout: false, //避免請求未完成時中斷
|
|
315
|
-
output: 'stream',
|
|
408
|
+
output: 'stream', //代表前端用stream傳至伺服器(Content-Type為application/octet-stream)
|
|
316
409
|
parse: false,
|
|
317
410
|
},
|
|
318
411
|
timeout: {
|
|
@@ -334,8 +427,7 @@ function WConverhpServer(opt = {}) {
|
|
|
334
427
|
query = iseobj(query) ? query : ''
|
|
335
428
|
// console.log('query', query)
|
|
336
429
|
|
|
337
|
-
//
|
|
338
|
-
// let token = get(query, 'token', '')
|
|
430
|
+
//authorization
|
|
339
431
|
let authorization = get(headers, 'authorization', '')
|
|
340
432
|
authorization = isestr(authorization) ? authorization : ''
|
|
341
433
|
|
|
@@ -350,16 +442,7 @@ function WConverhpServer(opt = {}) {
|
|
|
350
442
|
|
|
351
443
|
//check
|
|
352
444
|
if (m !== true) {
|
|
353
|
-
|
|
354
|
-
//u8aOut
|
|
355
|
-
let out = {
|
|
356
|
-
error: 'permission denied',
|
|
357
|
-
}
|
|
358
|
-
let u8aOut = obj2u8arr(out)
|
|
359
|
-
// console.log('main u8aOut', u8aOut)
|
|
360
|
-
|
|
361
|
-
// console.log('main return permission denied')
|
|
362
|
-
return responseU8aStream(res, u8aOut)
|
|
445
|
+
return responseU8aStreamWithError(res, 'permission denied')
|
|
363
446
|
}
|
|
364
447
|
|
|
365
448
|
}
|
|
@@ -377,21 +460,15 @@ function WConverhpServer(opt = {}) {
|
|
|
377
460
|
//pm
|
|
378
461
|
let pm = genPm()
|
|
379
462
|
|
|
380
|
-
//
|
|
381
|
-
// let totalSize = 0
|
|
463
|
+
//chunks
|
|
382
464
|
let chunks = []
|
|
383
|
-
|
|
384
|
-
//smw
|
|
385
465
|
let smw = new stream.Writable({
|
|
386
466
|
write(chunk, encoding, cb) {
|
|
387
467
|
// console.log('receive payload', chunk)
|
|
388
468
|
|
|
389
|
-
// //totalSize
|
|
390
|
-
// totalSize += chunk.length
|
|
391
|
-
|
|
392
469
|
//push
|
|
393
470
|
chunks.push(chunk)
|
|
394
|
-
// console.log('chunk.length', chunk.length
|
|
471
|
+
// console.log('chunk.length', chunk.length)
|
|
395
472
|
|
|
396
473
|
//setTimeout, 延遲觸發cb
|
|
397
474
|
setTimeout(() => {
|
|
@@ -408,7 +485,7 @@ function WConverhpServer(opt = {}) {
|
|
|
408
485
|
req.payload.on('end', () => {
|
|
409
486
|
// console.log(`receive payload done`)
|
|
410
487
|
|
|
411
|
-
//
|
|
488
|
+
//fileBuffer
|
|
412
489
|
let fileBuffer = Buffer.concat(chunks)
|
|
413
490
|
// console.log('fileBuffer', fileBuffer, fileBuffer.length)
|
|
414
491
|
|
|
@@ -444,12 +521,18 @@ function WConverhpServer(opt = {}) {
|
|
|
444
521
|
|
|
445
522
|
//procDeal
|
|
446
523
|
let out = {}
|
|
524
|
+
let returnType = ''
|
|
525
|
+
let returnMsg = ''
|
|
447
526
|
await procDeal(inp)
|
|
448
527
|
.then(function(msg) {
|
|
449
528
|
out.success = msg
|
|
529
|
+
returnType = 'success'
|
|
530
|
+
returnMsg = 'need to parse'
|
|
450
531
|
})
|
|
451
532
|
.catch(function(msg) {
|
|
452
533
|
out.error = msg
|
|
534
|
+
returnType = 'error'
|
|
535
|
+
returnMsg = 'need to parse'
|
|
453
536
|
})
|
|
454
537
|
// console.log('out', out)
|
|
455
538
|
|
|
@@ -457,20 +540,20 @@ function WConverhpServer(opt = {}) {
|
|
|
457
540
|
let u8aOut = obj2u8arr(out)
|
|
458
541
|
// console.log('u8aOut', u8aOut)
|
|
459
542
|
|
|
460
|
-
return responseU8aStream(res, u8aOut)
|
|
543
|
+
return responseU8aStream(res, u8aOut, { returnType, returnMsg })
|
|
461
544
|
},
|
|
462
545
|
}
|
|
463
546
|
|
|
464
|
-
//
|
|
465
|
-
let
|
|
466
|
-
path: `/${
|
|
547
|
+
//apiUploadSlice
|
|
548
|
+
let apiUploadSlice = {
|
|
549
|
+
path: `/${apiUploadSliceName}`,
|
|
467
550
|
method: 'POST',
|
|
468
551
|
options: {
|
|
469
552
|
payload: {
|
|
470
553
|
maxBytes: 1024 * 1024 * 1024 * 1024, //預設為1mb, 調整至1tb, 也就是給予3次方
|
|
471
554
|
maxParts: 1000 * 1000 * 1000, //預設為1000, 給予3次方
|
|
472
555
|
timeout: false, //避免請求未完成時中斷
|
|
473
|
-
output: 'stream',
|
|
556
|
+
output: 'stream', //代表前端用stream傳至伺服器(Content-Type為application/octet-stream)
|
|
474
557
|
parse: false,
|
|
475
558
|
},
|
|
476
559
|
timeout: {
|
|
@@ -492,8 +575,7 @@ function WConverhpServer(opt = {}) {
|
|
|
492
575
|
query = iseobj(query) ? query : ''
|
|
493
576
|
// console.log('query', query)
|
|
494
577
|
|
|
495
|
-
//
|
|
496
|
-
// let token = get(query, 'token', '')
|
|
578
|
+
//authorization
|
|
497
579
|
let authorization = get(headers, 'authorization', '')
|
|
498
580
|
authorization = isestr(authorization) ? authorization : ''
|
|
499
581
|
|
|
@@ -501,30 +583,21 @@ function WConverhpServer(opt = {}) {
|
|
|
501
583
|
if (true) {
|
|
502
584
|
|
|
503
585
|
//verifyConn
|
|
504
|
-
let m = verifyConn({ apiType: 'slice', authorization, headers, query })
|
|
586
|
+
let m = verifyConn({ apiType: 'upload-slice', authorization, headers, query })
|
|
505
587
|
if (ispm(m)) {
|
|
506
588
|
m = await m
|
|
507
589
|
}
|
|
508
590
|
|
|
509
591
|
//check
|
|
510
592
|
if (m !== true) {
|
|
511
|
-
|
|
512
|
-
//u8aOut
|
|
513
|
-
let out = {
|
|
514
|
-
error: 'permission denied',
|
|
515
|
-
}
|
|
516
|
-
let u8aOut = obj2u8arr(out)
|
|
517
|
-
// console.log('slice u8aOut', u8aOut)
|
|
518
|
-
|
|
519
|
-
// console.log('slice return permission denied')
|
|
520
|
-
return responseU8aStream(res, u8aOut)
|
|
593
|
+
return responseU8aStreamWithError(res, 'permission denied')
|
|
521
594
|
}
|
|
522
595
|
|
|
523
596
|
}
|
|
524
597
|
|
|
525
598
|
//eeEmit
|
|
526
599
|
eeEmit('handler', {
|
|
527
|
-
api: '
|
|
600
|
+
api: 'apiUploadSlice',
|
|
528
601
|
headers,
|
|
529
602
|
query,
|
|
530
603
|
})
|
|
@@ -590,12 +663,18 @@ function WConverhpServer(opt = {}) {
|
|
|
590
663
|
|
|
591
664
|
//receive
|
|
592
665
|
let out = {}
|
|
666
|
+
let returnType = ''
|
|
667
|
+
let returnMsg = ''
|
|
593
668
|
await receive()
|
|
594
669
|
.then(function(msg) {
|
|
595
670
|
out.success = msg
|
|
671
|
+
returnType = 'success'
|
|
672
|
+
returnMsg = 'need to parse'
|
|
596
673
|
})
|
|
597
674
|
.catch(function(msg) {
|
|
598
675
|
out.error = msg
|
|
676
|
+
returnType = 'error'
|
|
677
|
+
returnMsg = 'need to parse'
|
|
599
678
|
})
|
|
600
679
|
// console.log('out', out)
|
|
601
680
|
|
|
@@ -603,13 +682,13 @@ function WConverhpServer(opt = {}) {
|
|
|
603
682
|
let u8aOut = obj2u8arr(out)
|
|
604
683
|
// console.log('u8aOut', u8aOut)
|
|
605
684
|
|
|
606
|
-
return responseU8aStream(res, u8aOut)
|
|
685
|
+
return responseU8aStream(res, u8aOut, { returnType, returnMsg })
|
|
607
686
|
},
|
|
608
687
|
}
|
|
609
688
|
|
|
610
|
-
//
|
|
611
|
-
let
|
|
612
|
-
path: `/${
|
|
689
|
+
//apiUploadSliceMerge
|
|
690
|
+
let apiUploadSliceMerge = {
|
|
691
|
+
path: `/${apiUploadSliceName}m`,
|
|
613
692
|
method: 'POST',
|
|
614
693
|
options: {
|
|
615
694
|
payload: {
|
|
@@ -638,8 +717,7 @@ function WConverhpServer(opt = {}) {
|
|
|
638
717
|
query = iseobj(query) ? query : ''
|
|
639
718
|
// console.log('query', query)
|
|
640
719
|
|
|
641
|
-
//
|
|
642
|
-
// let token = get(query, 'token', '')
|
|
720
|
+
//authorization
|
|
643
721
|
let authorization = get(headers, 'authorization', '')
|
|
644
722
|
authorization = isestr(authorization) ? authorization : ''
|
|
645
723
|
|
|
@@ -647,30 +725,21 @@ function WConverhpServer(opt = {}) {
|
|
|
647
725
|
if (true) {
|
|
648
726
|
|
|
649
727
|
//verifyConn
|
|
650
|
-
let m = verifyConn({ apiType: 'merge', authorization, headers, query })
|
|
728
|
+
let m = verifyConn({ apiType: 'upload-slice-merge', authorization, headers, query })
|
|
651
729
|
if (ispm(m)) {
|
|
652
730
|
m = await m
|
|
653
731
|
}
|
|
654
732
|
|
|
655
733
|
//check
|
|
656
734
|
if (m !== true) {
|
|
657
|
-
|
|
658
|
-
//u8aOut
|
|
659
|
-
let out = {
|
|
660
|
-
error: 'permission denied',
|
|
661
|
-
}
|
|
662
|
-
let u8aOut = obj2u8arr(out)
|
|
663
|
-
// console.log('mergeu8aOut', u8aOut)
|
|
664
|
-
|
|
665
|
-
// console.log('merge return permission denied')
|
|
666
|
-
return responseU8aStream(res, u8aOut)
|
|
735
|
+
return responseU8aStreamWithError(res, 'permission denied')
|
|
667
736
|
}
|
|
668
737
|
|
|
669
738
|
}
|
|
670
739
|
|
|
671
740
|
//eeEmit
|
|
672
741
|
eeEmit('handler', {
|
|
673
|
-
api: '
|
|
742
|
+
api: 'apiUploadSliceMerge',
|
|
674
743
|
headers,
|
|
675
744
|
query,
|
|
676
745
|
})
|
|
@@ -714,12 +783,18 @@ function WConverhpServer(opt = {}) {
|
|
|
714
783
|
|
|
715
784
|
//core
|
|
716
785
|
let out = {}
|
|
786
|
+
let returnType = ''
|
|
787
|
+
let returnMsg = ''
|
|
717
788
|
await core()
|
|
718
789
|
.then(function(msg) {
|
|
719
790
|
out.success = msg
|
|
791
|
+
returnType = 'success'
|
|
792
|
+
returnMsg = 'need to parse'
|
|
720
793
|
})
|
|
721
794
|
.catch(function(msg) {
|
|
722
795
|
out.error = msg
|
|
796
|
+
returnType = 'error'
|
|
797
|
+
returnMsg = 'need to parse'
|
|
723
798
|
})
|
|
724
799
|
// console.log('out', out)
|
|
725
800
|
|
|
@@ -727,7 +802,118 @@ function WConverhpServer(opt = {}) {
|
|
|
727
802
|
let u8aOut = obj2u8arr(out)
|
|
728
803
|
// console.log('u8aOut', u8aOut)
|
|
729
804
|
|
|
730
|
-
return responseU8aStream(res, u8aOut)
|
|
805
|
+
return responseU8aStream(res, u8aOut, { returnType, returnMsg })
|
|
806
|
+
},
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
//apiDownload
|
|
810
|
+
let apiDownload = {
|
|
811
|
+
path: `/${apiDownloadName}`,
|
|
812
|
+
method: 'POST',
|
|
813
|
+
options: {
|
|
814
|
+
payload: {
|
|
815
|
+
maxBytes: 1024 * 1024 * 1024 * 1024, //預設為1mb, 調整至1tb, 也就是給予3次方
|
|
816
|
+
maxParts: 1000 * 1000 * 1000, //預設為1000, 給予3次方
|
|
817
|
+
timeout: false, //避免請求未完成時中斷
|
|
818
|
+
// output: 'stream',
|
|
819
|
+
parse: true, //前端送obj過來
|
|
820
|
+
},
|
|
821
|
+
timeout: {
|
|
822
|
+
server: false, //關閉伺服器超時
|
|
823
|
+
socket: false, //關閉socket超時
|
|
824
|
+
},
|
|
825
|
+
},
|
|
826
|
+
handler: async function (req, res) {
|
|
827
|
+
// console.log(req, res)
|
|
828
|
+
// console.log('payload', req.payload)
|
|
829
|
+
|
|
830
|
+
//headers
|
|
831
|
+
let headers = get(req, 'headers')
|
|
832
|
+
headers = iseobj(headers) ? headers : ''
|
|
833
|
+
// console.log('headers', headers)
|
|
834
|
+
|
|
835
|
+
//query
|
|
836
|
+
let query = get(req, 'query')
|
|
837
|
+
query = iseobj(query) ? query : ''
|
|
838
|
+
// console.log('query', query)
|
|
839
|
+
|
|
840
|
+
//authorization
|
|
841
|
+
let authorization = get(headers, 'authorization', '')
|
|
842
|
+
authorization = isestr(authorization) ? authorization : ''
|
|
843
|
+
|
|
844
|
+
//check
|
|
845
|
+
if (true) {
|
|
846
|
+
|
|
847
|
+
//verifyConn
|
|
848
|
+
let m = verifyConn({ apiType: 'download', authorization, headers, query })
|
|
849
|
+
if (ispm(m)) {
|
|
850
|
+
m = await m
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
//check
|
|
854
|
+
if (m !== true) {
|
|
855
|
+
return responseU8aStreamWithError(res, 'permission denied')
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
//eeEmit
|
|
861
|
+
eeEmit('handler', {
|
|
862
|
+
api: 'apiDownload',
|
|
863
|
+
headers,
|
|
864
|
+
query,
|
|
865
|
+
})
|
|
866
|
+
|
|
867
|
+
//fileId, 從payload接收
|
|
868
|
+
let fileId = get(req, 'payload.fileId', '')
|
|
869
|
+
// console.log('fileId', fileId)
|
|
870
|
+
|
|
871
|
+
//check
|
|
872
|
+
if (!isestr(fileId)) {
|
|
873
|
+
// console.log('invalid fileId in payload')
|
|
874
|
+
return responseU8aStreamWithError(res, 'invalid fileId in payload')
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
//inp
|
|
878
|
+
let inp = { fileId }
|
|
879
|
+
|
|
880
|
+
//procDownload
|
|
881
|
+
let out = {}
|
|
882
|
+
await procDownload(inp)
|
|
883
|
+
.then(function(msg) {
|
|
884
|
+
out.success = msg
|
|
885
|
+
})
|
|
886
|
+
.catch(function(msg) {
|
|
887
|
+
out.error = msg
|
|
888
|
+
})
|
|
889
|
+
// console.log('out', out)
|
|
890
|
+
|
|
891
|
+
//return
|
|
892
|
+
if (haskey(out, 'error')) {
|
|
893
|
+
// console.log('out.error', out.error)
|
|
894
|
+
return responseU8aStreamWithError(res, `can not get file from fileId[${fileId}]`)
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
//streamRead, fileName, fileSize, fileType
|
|
898
|
+
let r = get(out, 'success')
|
|
899
|
+
let streamRead = get(r, 'streamRead')
|
|
900
|
+
let fileName = get(r, 'fileName')
|
|
901
|
+
if (!isestr(fileName)) {
|
|
902
|
+
return res.response({ error: `invalid fileName` }).code(400)
|
|
903
|
+
}
|
|
904
|
+
let fileSize = get(r, 'fileSize')
|
|
905
|
+
if (!isnum(fileSize)) {
|
|
906
|
+
return res.response({ error: `invalid fileSize` }).code(400)
|
|
907
|
+
}
|
|
908
|
+
let fileType = get(r, 'fileType')
|
|
909
|
+
if (!isestr(fileType)) {
|
|
910
|
+
return res.response({ error: `invalid fileType` }).code(400)
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
return res.response(streamRead)
|
|
914
|
+
.type(fileType)
|
|
915
|
+
.header('Content-Disposition', `attachment; filename="${fileName}"`)
|
|
916
|
+
.header('Content-Length', fileSize)
|
|
731
917
|
},
|
|
732
918
|
}
|
|
733
919
|
|
|
@@ -760,8 +946,9 @@ function WConverhpServer(opt = {}) {
|
|
|
760
946
|
apiRoutes = [
|
|
761
947
|
...apiRoutes,
|
|
762
948
|
apiMain,
|
|
763
|
-
|
|
764
|
-
|
|
949
|
+
apiUploadSlice,
|
|
950
|
+
apiUploadSliceMerge,
|
|
951
|
+
apiDownload,
|
|
765
952
|
]
|
|
766
953
|
}
|
|
767
954
|
|
|
@@ -777,8 +964,8 @@ function WConverhpServer(opt = {}) {
|
|
|
777
964
|
|
|
778
965
|
//start
|
|
779
966
|
if (get(opt, 'serverHapi')) {
|
|
780
|
-
// opt.serverHapi.route([apiMain,
|
|
781
|
-
server.route([apiMain,
|
|
967
|
+
// opt.serverHapi.route([apiMain, apiUploadSlice, apiUploadSliceMerge, apiDownload])
|
|
968
|
+
server.route([apiMain, apiUploadSlice, apiUploadSliceMerge, apiDownload])
|
|
782
969
|
}
|
|
783
970
|
else {
|
|
784
971
|
startServer()
|
package/src/mergeFiles.mjs
CHANGED
|
@@ -1,116 +1,27 @@
|
|
|
1
1
|
import path from 'path'
|
|
2
|
-
import
|
|
3
|
-
import genPm from 'wsemi/src/genPm.mjs'
|
|
4
|
-
import fsIsFile from 'wsemi/src/fsIsFile.mjs'
|
|
5
|
-
import fsDeleteFile from 'wsemi/src/fsDeleteFile.mjs'
|
|
2
|
+
import fsMergeFiles from 'wsemi/src/fsMergeFiles.mjs'
|
|
6
3
|
|
|
7
4
|
|
|
8
5
|
let mergeFiles = async (pathUploadTemp, packageId, chunkTotal, filename) => {
|
|
9
|
-
let errTemp = ''
|
|
10
6
|
|
|
11
|
-
//
|
|
12
|
-
let
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
// console.log('pathFileMerge', pathFileMerge)
|
|
20
|
-
|
|
21
|
-
//streamWrite
|
|
22
|
-
let streamWrite = fs.createWriteStream(pathFileMerge)
|
|
23
|
-
// console.log(`merge filename[${filename}] start`)
|
|
24
|
-
|
|
25
|
-
for (let i = 0; i < chunkTotal; i++) {
|
|
26
|
-
// console.log(`merge ${i + 1}/${chunkTotal}`)
|
|
27
|
-
|
|
28
|
-
//chunkIndex
|
|
29
|
-
let chunkIndex = i
|
|
30
|
-
|
|
31
|
-
//pathFileChunk
|
|
32
|
-
let pathFileChunk = path.join(pathUploadTemp, `${packageId}_${chunkIndex}`)
|
|
33
|
-
|
|
34
|
-
//check
|
|
35
|
-
if (!fsIsFile(pathFileChunk)) {
|
|
36
|
-
// console.log(`pathFileChunk[${pathFileChunk}] is not a file`)
|
|
37
|
-
throw new Error(`missing chunk ${i} of filename[${filename}]`)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// console.log(`merging chunk[${chunkIndex + 1}/${chunkTotal}]...`)
|
|
41
|
-
|
|
42
|
-
//使用readFileSync會忽略背壓, 若寫入相對慢就會儲存至記憶體, 導致記憶體超量使用, 得要偵測與控制背壓
|
|
43
|
-
// //chunkData
|
|
44
|
-
// let chunkData = fs.readFileSync(pathFileChunk)
|
|
45
|
-
// //write
|
|
46
|
-
// streamWrite.write(chunkData)
|
|
47
|
-
// //fsDeleteFile
|
|
48
|
-
// fsDeleteFile(pathFileChunk)
|
|
49
|
-
|
|
50
|
-
//transfer
|
|
51
|
-
let transfer = () => {
|
|
52
|
-
let pmc = genPm()
|
|
53
|
-
|
|
54
|
-
//streamRead
|
|
55
|
-
let streamRead = fs.createReadStream(pathFileChunk)
|
|
56
|
-
|
|
57
|
-
//監測錯誤
|
|
58
|
-
streamRead.on('error', (err) => {
|
|
59
|
-
errTemp = err.message
|
|
60
|
-
pmc.reject(err)
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
//監測串流結束
|
|
64
|
-
streamRead.on('end', () => {
|
|
65
|
-
fsDeleteFile(pathFileChunk)
|
|
66
|
-
pmc.resolve()
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
//pipe, 將讀取流接入寫入流, 會自動調節讀寫速率處理背壓
|
|
70
|
-
//注意pipe不會自動處理錯誤, 若read出錯也不會因pipe轉移至write, 故read的錯誤得要獨立監聽處理
|
|
71
|
-
streamRead.pipe(streamWrite, { end: false })
|
|
72
|
-
|
|
73
|
-
return pmc
|
|
74
|
-
}
|
|
75
|
-
await transfer()
|
|
76
|
-
|
|
77
|
-
// console.log(`merge chunk[${chunkIndex + 1}/${chunkTotal}] done`)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
//end
|
|
81
|
-
streamWrite.end()
|
|
82
|
-
|
|
83
|
-
//error, 若有error則不會觸發finish
|
|
84
|
-
streamWrite.on('error', (err) => {
|
|
85
|
-
// console.log(`merge filename[${filename}] err`, err)
|
|
86
|
-
errTemp = err.message
|
|
87
|
-
pm.reject(errTemp)
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
//finish, end之後檔案未必完成寫入會有時間差, 得要監聽finish才能確定寫入檔案完成
|
|
91
|
-
streamWrite.on('finish', () => {
|
|
92
|
-
// console.log(`merge filename[${filename}] end`)
|
|
93
|
-
|
|
94
|
-
//r
|
|
95
|
-
let r = {
|
|
96
|
-
filename,
|
|
97
|
-
path: pathFileMerge,
|
|
98
|
-
}
|
|
99
|
-
// let s = fs.statSync(pathFileMerge)
|
|
100
|
-
// console.log('s.size', s.size)
|
|
101
|
-
|
|
102
|
-
//resolve
|
|
103
|
-
pm.resolve(r)
|
|
7
|
+
//fpsIn
|
|
8
|
+
let fpsIn = []
|
|
9
|
+
for (let i = 0; i < chunkTotal; i++) {
|
|
10
|
+
let fpIn = path.join(pathUploadTemp, `${packageId}_${i}`)
|
|
11
|
+
// console.log('fpIn', fpIn)
|
|
12
|
+
fpsIn.push(fpIn)
|
|
13
|
+
}
|
|
14
|
+
// console.log('fpsIn', fpsIn)
|
|
104
15
|
|
|
105
|
-
|
|
16
|
+
//fpOut
|
|
17
|
+
let fpOut = path.join(pathUploadTemp, packageId)
|
|
18
|
+
// console.log('fpOut', fpOut)
|
|
106
19
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
pm.reject(errTemp)
|
|
111
|
-
}
|
|
20
|
+
//fsMergeFiles
|
|
21
|
+
let r = await fsMergeFiles(filename, fpsIn, fpOut)
|
|
22
|
+
// console.log('r', r)
|
|
112
23
|
|
|
113
|
-
return
|
|
24
|
+
return r
|
|
114
25
|
}
|
|
115
26
|
|
|
116
27
|
export default mergeFiles
|