w-converhp 2.0.13 → 2.0.15

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.
@@ -3,6 +3,7 @@ import stream from 'stream'
3
3
  import Hapi from '@hapi/hapi'
4
4
  import Inert from '@hapi/inert' //提供靜態檔案
5
5
  import get from 'lodash-es/get.js'
6
+ import isNumber from 'lodash-es/isNumber.js'
6
7
  import genPm from 'wsemi/src/genPm.mjs'
7
8
  import evem from 'wsemi/src/evem.mjs'
8
9
  import iseobj from 'wsemi/src/iseobj.mjs'
@@ -12,9 +13,10 @@ import ispint from 'wsemi/src/ispint.mjs'
12
13
  import isearr from 'wsemi/src/isearr.mjs'
13
14
  import isbol from 'wsemi/src/isbol.mjs'
14
15
  import isfun from 'wsemi/src/isfun.mjs'
15
- import isnum from 'wsemi/src/isnum.mjs'
16
16
  import ispm from 'wsemi/src/ispm.mjs'
17
17
  import cint from 'wsemi/src/cint.mjs'
18
+ import cstr from 'wsemi/src/cstr.mjs'
19
+ import str2b64 from 'wsemi/src/str2b64.mjs'
18
20
  import haskey from 'wsemi/src/haskey.mjs'
19
21
  import obj2u8arr from 'wsemi/src/obj2u8arr.mjs'
20
22
  import u8arr2obj from 'wsemi/src/u8arr2obj.mjs'
@@ -24,6 +26,11 @@ import mergeFiles from './mergeFiles.wk.umd.js'
24
26
  // import mergeFiles from './mergeFiles.mjs'
25
27
 
26
28
 
29
+ //回傳前端stream時(POST或GET皆可), 前端會須等stream傳完才能判斷是否為大檔或錯誤訊息, 此會導致若回傳超大檔, 會需要對超大檔進行解析會有記憶體上限問題, 故需要通過header提供基本成功或失敗訊息, 讓前端能進行解析判斷
30
+ //回傳前端(nodejs)時, 針對超大檔, 只能用POST並用stream回傳
31
+ //回傳前端(browser)時, 針對超大檔, 可用POST並用stream回傳但還要處理進度條, 若要交由瀏覽器下載器處理, 只能用GET並用stream回傳, 且前端只能用window.location.href或a.href+a.click()下載
32
+
33
+
27
34
  /**
28
35
  * 建立Hapi伺服器
29
36
  *
@@ -34,6 +41,7 @@ import mergeFiles from './mergeFiles.wk.umd.js'
34
41
  * @param {String} [opt.pathStaticFiles='dist'] 輸入當useInert=true時提供瀏覽資料夾字串,預設'dist'
35
42
  * @param {String} [opt.apiName='api'] 輸入API名稱字串,預設'api'
36
43
  * @param {String} [opt.pathUploadTemp='./uploadTemp'] 輸入暫時存放切片上傳檔案資料夾字串,預設'./uploadTemp'
44
+ * @param {String} [opt.tokenType='Bearer'] 輸入token類型字串,預設'Bearer'
37
45
  * @param {Function} [opt.verifyConn=()=>{return true}] 輸入呼叫API時檢測函數,預設()=>{return true}
38
46
  * @param {Array} [opt.corsOrigins=['*']] 輸入允許跨域網域陣列,若給予['*']代表允許全部,預設['*']
39
47
  * @param {Integer} [opt.delayForBasic=0] 輸入基本API用延遲響應時間,單位ms,預設0
@@ -42,14 +50,24 @@ import mergeFiles from './mergeFiles.wk.umd.js'
42
50
  * @returns {Object} 回傳事件物件,可監聽事件execute、upload、handler
43
51
  * @example
44
52
  *
53
+ * import fs from 'fs'
45
54
  * import _ from 'lodash-es'
46
- * import WConverhpServer from 'w-converhp/dist/w-converhp-server.umd.js'
55
+ * import w from 'wsemi'
56
+ * import WConverhpServer from './src/WConverhpServer.mjs'
57
+ *
58
+ * let ms = []
47
59
  *
48
60
  * let opt = {
49
61
  * port: 8080,
50
62
  * apiName: 'api',
51
63
  * pathStaticFiles: '.', //要存取專案資料夾下web.html, 故不能給dist
52
- * verifyConn: () => {
64
+ * verifyConn: async ({ apiType, authorization, headers, query }) => {
65
+ * console.log('verifyConn', `apiType[${apiType}]`, `authorization[${authorization}]`)
66
+ * let token = w.strdelleft(authorization, 7) //刪除Bearer
67
+ * if (!w.isestr(token)) {
68
+ * return false
69
+ * }
70
+ * // await w.delay(3000)
53
71
  * return true
54
72
  * },
55
73
  * }
@@ -67,6 +85,7 @@ import mergeFiles from './mergeFiles.wk.umd.js'
67
85
  *
68
86
  * if (_.get(input, 'p.d.u8a', null)) {
69
87
  * console.log('input.p.d.u8a', input.p.d.u8a)
88
+ * ms.push({ 'input.p.d.u8a': input.p.d.u8a })
70
89
  * }
71
90
  *
72
91
  * let r = {
@@ -74,13 +93,7 @@ import mergeFiles from './mergeFiles.wk.umd.js'
74
93
  * _data: [11, 22.22, 'abc', { x: '21', y: 65.43, z: 'test中文' }],
75
94
  * _bin: {
76
95
  * name: 'zdata.b2',
77
- * u8a: new Uint8Array([66, 97, 115]),
78
- * // name: '100mb.7z',
79
- * // u8a: new Uint8Array(fs.readFileSync('D:\\開源-JS-006-2-w-converhp\\_temp\\100mb.7z')),
80
- * // name: '500mb.7z',
81
- * // u8a: new Uint8Array(fs.readFileSync('D:\\開源-JS-006-2-w-converhp\\_temp\\500mb.7z')),
82
- * // name: '1000mb.7z',
83
- * // u8a: new Uint8Array(fs.readFileSync('D:\\開源-JS-006-2-w-converhp\\_temp\\1000mb.7z')),
96
+ * u8a: new Uint8Array([52, 66, 97, 115]),
84
97
  * },
85
98
  * }
86
99
  *
@@ -103,6 +116,7 @@ import mergeFiles from './mergeFiles.wk.umd.js'
103
116
  * console.log(`Server[port:${opt.port}]: upload`, input)
104
117
  *
105
118
  * try {
119
+ * ms.push({ 'receive and return': input })
106
120
  * let output = input
107
121
  * pm.resolve(output)
108
122
  * }
@@ -112,6 +126,28 @@ import mergeFiles from './mergeFiles.wk.umd.js'
112
126
  * }
113
127
  *
114
128
  * })
129
+ * wo.on('download-get-filename', (input, pm) => {
130
+ * console.log(`Server[port:${opt.port}]: download-get-filename`, input)
131
+ *
132
+ * try {
133
+ * ms.push({ 'download': input })
134
+ *
135
+ * //filename
136
+ * let filename = `1mb中文.7z` //測試支援中文
137
+ *
138
+ * //output
139
+ * let output = {
140
+ * filename
141
+ * }
142
+ *
143
+ * pm.resolve(output)
144
+ * }
145
+ * catch (err) {
146
+ * console.log('download error', err)
147
+ * pm.reject('download error')
148
+ * }
149
+ *
150
+ * })
115
151
  * wo.on('download', (input, pm) => {
116
152
  * console.log(`Server[port:${opt.port}]: download`, input)
117
153
  *
@@ -125,7 +161,7 @@ import mergeFiles from './mergeFiles.wk.umd.js'
125
161
  * let streamRead = fs.createReadStream(fp)
126
162
  *
127
163
  * //fileName
128
- * let fileName = `1mb.7z`
164
+ * let fileName = `1mb中文.7z` //測試支援中文
129
165
  *
130
166
  * //fileSize
131
167
  * let stats = fs.statSync(fp)
@@ -150,10 +186,19 @@ import mergeFiles from './mergeFiles.wk.umd.js'
150
186
  * }
151
187
  *
152
188
  * })
189
+ * wo.on('error', (err) => {
190
+ * console.log(`Server[port:${opt.port}]: error`, err)
191
+ * })
153
192
  * wo.on('handler', (data) => {
154
193
  * // console.log(`Server[port:${opt.port}]: handler`, data)
155
194
  * })
156
195
  *
196
+ * setTimeout(() => {
197
+ * console.log('ms', ms)
198
+ * // console.log('ms', JSON.stringify(ms))
199
+ * wo.stop()
200
+ * }, 3000)
201
+ *
157
202
  */
158
203
  function WConverhpServer(opt = {}) {
159
204
 
@@ -181,12 +226,6 @@ function WConverhpServer(opt = {}) {
181
226
  apiName = 'api'
182
227
  }
183
228
 
184
- //apiUploadSliceName
185
- let apiUploadSliceName = `${apiName}slc`
186
-
187
- //apiDownloadName
188
- let apiDownloadName = `${apiName}dw`
189
-
190
229
  //pathUploadTemp
191
230
  let pathUploadTemp = get(opt, 'pathUploadTemp')
192
231
  if (!isestr(pathUploadTemp)) {
@@ -196,6 +235,12 @@ function WConverhpServer(opt = {}) {
196
235
  fsCreateFolder(pathUploadTemp)
197
236
  }
198
237
 
238
+ //tokenType
239
+ let tokenType = get(opt, 'tokenType')
240
+ if (!isestr(tokenType)) {
241
+ tokenType = 'Bearer'
242
+ }
243
+
199
244
  //verifyConn
200
245
  let verifyConn = get(opt, 'verifyConn')
201
246
  if (!isfun(verifyConn)) {
@@ -331,6 +376,36 @@ function WConverhpServer(opt = {}) {
331
376
  return pm
332
377
  }
333
378
 
379
+ //procDownloadGetFilename
380
+ async function procDownloadGetFilename(input) {
381
+ // console.log('procDownloadGetFilename', input)
382
+
383
+ //pm, pmm
384
+ let pm = genPm()
385
+ let pmm = genPm()
386
+
387
+ //重新處理回傳結果
388
+ pmm
389
+ .then((output) => {
390
+
391
+ //resolve
392
+ pm.resolve(output)
393
+
394
+ })
395
+ .catch((err) => {
396
+ pm.reject(err)
397
+ })
398
+
399
+ if (true) {
400
+
401
+ //download, 下載檔案
402
+ eeEmit('download-get-filename', input, pmm)
403
+
404
+ }
405
+
406
+ return pm
407
+ }
408
+
334
409
  //procDownload
335
410
  async function procDownload(input) {
336
411
  // console.log('procDownload', input)
@@ -387,12 +462,22 @@ function WConverhpServer(opt = {}) {
387
462
  //responseU8aStreamWithError
388
463
  function responseU8aStreamWithError(res, msg) {
389
464
 
465
+ //check
466
+ if (!isestr(msg)) {
467
+ console.log('msg', msg)
468
+ console.log(`msg is not an effective string, set msg=''`)
469
+ msg = ''
470
+ }
471
+
390
472
  //u8aOut
391
473
  let u8aOut = obj2u8arr({
392
474
  error: msg,
393
475
  })
394
476
  // console.log('download u8aOut', u8aOut)
395
477
 
478
+ //str2b64
479
+ // msg = str2b64(msg) //預期程式內調用皆為英文, 不須轉base64來支援中文
480
+
396
481
  return responseU8aStream(res, u8aOut, { returnType: 'error', returnMsg: msg })
397
482
  }
398
483
 
@@ -546,7 +631,7 @@ function WConverhpServer(opt = {}) {
546
631
 
547
632
  //apiUploadSlice
548
633
  let apiUploadSlice = {
549
- path: `/${apiUploadSliceName}`,
634
+ path: `/${apiName}slc`,
550
635
  method: 'POST',
551
636
  options: {
552
637
  payload: {
@@ -688,7 +773,7 @@ function WConverhpServer(opt = {}) {
688
773
 
689
774
  //apiUploadSliceMerge
690
775
  let apiUploadSliceMerge = {
691
- path: `/${apiUploadSliceName}m`,
776
+ path: `/${apiName}slcm`,
692
777
  method: 'POST',
693
778
  options: {
694
779
  payload: {
@@ -696,7 +781,7 @@ function WConverhpServer(opt = {}) {
696
781
  maxParts: 1000 * 1000 * 1000, //預設為1000, 給予3次方
697
782
  timeout: false, //避免請求未完成時中斷
698
783
  // output: 'stream',
699
- parse: true, //前端送obj過來
784
+ parse: true, //前端送obj過來須自動解析
700
785
  },
701
786
  timeout: {
702
787
  server: false, //關閉伺服器超時
@@ -806,9 +891,229 @@ function WConverhpServer(opt = {}) {
806
891
  },
807
892
  }
808
893
 
894
+ //apiDownloadGetFilename
895
+ let apiDownloadGetFilename = {
896
+ path: `/${apiName}dwgfn`,
897
+ method: 'POST',
898
+ options: {
899
+ payload: {
900
+ maxBytes: 1024 * 1024 * 1024 * 1024, //預設為1mb, 調整至1tb, 也就是給予3次方
901
+ maxParts: 1000 * 1000 * 1000, //預設為1000, 給予3次方
902
+ timeout: false, //避免請求未完成時中斷
903
+ // output: 'stream',
904
+ parse: true, //前端送obj過來須自動解析
905
+ },
906
+ timeout: {
907
+ server: false, //關閉伺服器超時
908
+ socket: false, //關閉socket超時
909
+ },
910
+ },
911
+ handler: async function (req, res) {
912
+ // console.log(req, res)
913
+ // console.log('payload', req.payload)
914
+
915
+ //headers
916
+ let headers = get(req, 'headers')
917
+ headers = iseobj(headers) ? headers : ''
918
+ // console.log('headers', headers)
919
+
920
+ //query
921
+ let query = get(req, 'query')
922
+ query = iseobj(query) ? query : ''
923
+ // console.log('query', query)
924
+
925
+ //authorization
926
+ let authorization = get(headers, 'authorization', '')
927
+ authorization = isestr(authorization) ? authorization : ''
928
+
929
+ //check
930
+ if (true) {
931
+
932
+ //verifyConn
933
+ let m = verifyConn({ apiType: 'download-get-filename', authorization, headers, query })
934
+ if (ispm(m)) {
935
+ m = await m
936
+ }
937
+
938
+ //check
939
+ if (m !== true) {
940
+ return responseU8aStreamWithError(res, 'permission denied')
941
+ }
942
+
943
+ }
944
+
945
+ //eeEmit
946
+ eeEmit('handler', {
947
+ api: 'apiDownloadGetFilename',
948
+ headers,
949
+ query,
950
+ })
951
+
952
+ //fileId, 從payload接收
953
+ let fileId = get(req, 'payload.fileId', '')
954
+ // console.log('fileId', fileId)
955
+
956
+ //check
957
+ if (!isestr(fileId)) {
958
+ // console.log('invalid fileId in payload')
959
+ return responseU8aStreamWithError(res, 'invalid fileId in payload')
960
+ }
961
+
962
+ //inp
963
+ let inp = { fileId }
964
+
965
+ //procDownloadGetFilename
966
+ let out = {}
967
+ let returnType = ''
968
+ let returnMsg = ''
969
+ await procDownloadGetFilename(inp)
970
+ .then(function(msg) {
971
+ out.success = msg
972
+ returnType = 'success'
973
+ returnMsg = 'need to parse'
974
+ })
975
+ .catch(function(msg) {
976
+ out.error = msg
977
+ returnType = 'error'
978
+ returnMsg = 'need to parse'
979
+ })
980
+ // console.log('out', out)
981
+
982
+ //u8aOut
983
+ let u8aOut = obj2u8arr(out)
984
+ // console.log('u8aOut', u8aOut)
985
+
986
+ return responseU8aStream(res, u8aOut, { returnType, returnMsg })
987
+ },
988
+ }
989
+
990
+ //apiDownloadGetFile
991
+ let apiDownloadGetFile = {
992
+ path: `/${apiName}dwgf`,
993
+ method: 'GET',
994
+ options: {
995
+ timeout: {
996
+ server: false, //關閉伺服器超時
997
+ socket: false, //關閉socket超時
998
+ },
999
+ },
1000
+ handler: async function (req, res) {
1001
+ // console.log(req, res)
1002
+ // console.log('payload', req.payload)
1003
+
1004
+ //headers
1005
+ let headers = get(req, 'headers')
1006
+ headers = iseobj(headers) ? headers : ''
1007
+ // console.log('headers', headers)
1008
+
1009
+ //query
1010
+ let query = get(req, 'query')
1011
+ query = iseobj(query) ? query : ''
1012
+ console.log('query', query)
1013
+
1014
+ //token
1015
+ let token = get(query, 'token', '')
1016
+ token = isestr(token) ? token : ''
1017
+ console.log('token', token)
1018
+
1019
+ //authorization
1020
+ let authorization = ''
1021
+ if (isestr(token)) {
1022
+ authorization = `${tokenType} ${token}`
1023
+ }
1024
+
1025
+ //check
1026
+ if (true) {
1027
+
1028
+ //verifyConn
1029
+ let m = verifyConn({ apiType: 'download-get-file', authorization, headers, query })
1030
+ if (ispm(m)) {
1031
+ m = await m
1032
+ }
1033
+
1034
+ //check
1035
+ if (m !== true) {
1036
+ return responseU8aStreamWithError(res, 'permission denied')
1037
+ }
1038
+
1039
+ }
1040
+
1041
+ //eeEmit
1042
+ eeEmit('handler', {
1043
+ api: 'apiDownloadGetFilename',
1044
+ headers,
1045
+ query,
1046
+ })
1047
+
1048
+ //fileId
1049
+ let fileId = get(query, 'fileId', '')
1050
+ fileId = isestr(fileId) ? fileId : ''
1051
+ console.log('fileId', fileId)
1052
+
1053
+ //check
1054
+ if (!isestr(fileId)) {
1055
+ // console.log('invalid fileId in query')
1056
+ return responseU8aStreamWithError(res, 'invalid fileId in query')
1057
+ }
1058
+
1059
+ //inp
1060
+ let inp = { fileId }
1061
+
1062
+ //procDownload
1063
+ let out = {}
1064
+ await procDownload(inp)
1065
+ .then(function(msg) {
1066
+ out.success = msg
1067
+ })
1068
+ .catch(function(msg) {
1069
+ out.error = msg
1070
+ })
1071
+ // console.log('out', out)
1072
+
1073
+ //return
1074
+ if (haskey(out, 'error')) {
1075
+ // console.log('out.error', out.error)
1076
+ return responseU8aStreamWithError(res, `can not get file from fileId`)
1077
+ }
1078
+
1079
+ //r
1080
+ let r = get(out, 'success')
1081
+
1082
+ //streamRead
1083
+ let streamRead = get(r, 'streamRead')
1084
+
1085
+ // //fileName
1086
+ // let fileName = get(r, 'fileName')
1087
+ // if (!isestr(fileName)) {
1088
+ // return responseU8aStreamWithError(res, 'invalid fileName')
1089
+ // }
1090
+ // fileName = str2b64(fileName) //headers內對中文支援度不佳須用base64傳
1091
+ // console.log('fileName', fileName)
1092
+
1093
+ //fileSize
1094
+ let fileSize = get(r, 'fileSize')
1095
+ if (!isNumber(fileSize)) {
1096
+ return responseU8aStreamWithError(res, 'invalid fileSize')
1097
+ }
1098
+ // fileSize = cstr(fileSize)
1099
+
1100
+ //fileType
1101
+ let fileType = get(r, 'fileType')
1102
+ if (!isestr(fileType)) {
1103
+ return responseU8aStreamWithError(res, 'invalid fileType')
1104
+ }
1105
+ fileType = cstr(fileType)
1106
+
1107
+ return res.response(streamRead)
1108
+ .type(fileType)
1109
+ // .header('Content-Disposition', `attachment; filename="${fileName}"`) //chrome會優先使用header內filename, 但header內支援中文度很差須用base64, 此導致chrome下載檔名只能為base64, 故一律改由前端(browser)先取得真實檔名後直接給予下載檔名, 避免用header提供真實檔名
1110
+ .header('Content-Length', fileSize)
1111
+ },
1112
+ }
1113
+
809
1114
  //apiDownload
810
1115
  let apiDownload = {
811
- path: `/${apiDownloadName}`,
1116
+ path: `/${apiName}dw`,
812
1117
  method: 'POST',
813
1118
  options: {
814
1119
  payload: {
@@ -816,7 +1121,7 @@ function WConverhpServer(opt = {}) {
816
1121
  maxParts: 1000 * 1000 * 1000, //預設為1000, 給予3次方
817
1122
  timeout: false, //避免請求未完成時中斷
818
1123
  // output: 'stream',
819
- parse: true, //前端送obj過來
1124
+ parse: true, //前端送obj過來須自動解析
820
1125
  },
821
1126
  timeout: {
822
1127
  server: false, //關閉伺服器超時
@@ -891,28 +1196,39 @@ function WConverhpServer(opt = {}) {
891
1196
  //return
892
1197
  if (haskey(out, 'error')) {
893
1198
  // console.log('out.error', out.error)
894
- return responseU8aStreamWithError(res, `can not get file from fileId[${fileId}]`)
1199
+ return responseU8aStreamWithError(res, `can not get file from fileId`)
895
1200
  }
896
1201
 
897
- //streamRead, fileName, fileSize, fileType
1202
+ //r
898
1203
  let r = get(out, 'success')
1204
+
1205
+ //streamRead
899
1206
  let streamRead = get(r, 'streamRead')
1207
+
1208
+ //fileName
900
1209
  let fileName = get(r, 'fileName')
901
1210
  if (!isestr(fileName)) {
902
- return res.response({ error: `invalid fileName` }).code(400)
1211
+ return responseU8aStreamWithError(res, 'invalid fileName')
903
1212
  }
1213
+ fileName = str2b64(fileName) //headers內對中文支援度不佳須用base64傳
1214
+
1215
+ //fileSize
904
1216
  let fileSize = get(r, 'fileSize')
905
- if (!isnum(fileSize)) {
906
- return res.response({ error: `invalid fileSize` }).code(400)
1217
+ if (!isNumber(fileSize)) {
1218
+ return responseU8aStreamWithError(res, 'invalid fileSize')
907
1219
  }
1220
+ // fileSize = cstr(fileSize)
1221
+
1222
+ //fileType
908
1223
  let fileType = get(r, 'fileType')
909
1224
  if (!isestr(fileType)) {
910
- return res.response({ error: `invalid fileType` }).code(400)
1225
+ return responseU8aStreamWithError(res, 'invalid fileType')
911
1226
  }
1227
+ fileType = cstr(fileType)
912
1228
 
913
1229
  return res.response(streamRead)
914
1230
  .type(fileType)
915
- .header('Content-Disposition', `attachment; filename="${fileName}"`)
1231
+ .header('Content-Disposition', `attachment; filename="${fileName}"`) //前端(nodejs)用POST下載代表, 可基於header內base64檔名解析出並直接給予檔名, 不用預先取得檔名
916
1232
  .header('Content-Length', fileSize)
917
1233
  },
918
1234
  }
@@ -948,6 +1264,8 @@ function WConverhpServer(opt = {}) {
948
1264
  apiMain,
949
1265
  apiUploadSlice,
950
1266
  apiUploadSliceMerge,
1267
+ apiDownloadGetFilename,
1268
+ apiDownloadGetFile,
951
1269
  apiDownload,
952
1270
  ]
953
1271
  }
@@ -964,8 +1282,7 @@ function WConverhpServer(opt = {}) {
964
1282
 
965
1283
  //start
966
1284
  if (get(opt, 'serverHapi')) {
967
- // opt.serverHapi.route([apiMain, apiUploadSlice, apiUploadSliceMerge, apiDownload])
968
- server.route([apiMain, apiUploadSlice, apiUploadSliceMerge, apiDownload])
1285
+ server.route([apiMain, apiUploadSlice, apiUploadSliceMerge, apiDownloadGetFilename, apiDownloadGetFile, apiDownload])
969
1286
  }
970
1287
  else {
971
1288
  startServer()
package/srv.mjs CHANGED
@@ -3,6 +3,7 @@ import _ from 'lodash-es'
3
3
  import w from 'wsemi'
4
4
  import WConverhpServer from './src/WConverhpServer.mjs'
5
5
 
6
+
6
7
  let ms = []
7
8
 
8
9
  let opt = {
@@ -73,6 +74,28 @@ wo.on('upload', (input, pm) => {
73
74
  pm.reject('upload error')
74
75
  }
75
76
 
77
+ })
78
+ wo.on('download-get-filename', (input, pm) => {
79
+ console.log(`Server[port:${opt.port}]: download-get-filename`, input)
80
+
81
+ try {
82
+ ms.push({ 'download': input })
83
+
84
+ //filename
85
+ let filename = `1mb中文.7z` //測試支援中文
86
+
87
+ //output
88
+ let output = {
89
+ filename
90
+ }
91
+
92
+ pm.resolve(output)
93
+ }
94
+ catch (err) {
95
+ console.log('download error', err)
96
+ pm.reject('download error')
97
+ }
98
+
76
99
  })
77
100
  wo.on('download', (input, pm) => {
78
101
  console.log(`Server[port:${opt.port}]: download`, input)
@@ -87,7 +110,7 @@ wo.on('download', (input, pm) => {
87
110
  let streamRead = fs.createReadStream(fp)
88
111
 
89
112
  //fileName
90
- let fileName = `1mb.7z`
113
+ let fileName = `1mb中文.7z` //測試支援中文
91
114
 
92
115
  //fileSize
93
116
  let stats = fs.statSync(fp)
@@ -123,7 +146,7 @@ setTimeout(() => {
123
146
  console.log('ms', ms)
124
147
  // console.log('ms', JSON.stringify(ms))
125
148
  wo.stop()
126
- }, 1113000)
149
+ }, 3000)
127
150
 
128
151
 
129
152
  //node --experimental-modules srv.mjs