@juzi/file-box 1.8.0 → 1.8.1

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.
Files changed (43) hide show
  1. package/README.md +3 -1
  2. package/dist/cjs/src/config.d.ts +5 -4
  3. package/dist/cjs/src/config.d.ts.map +1 -1
  4. package/dist/cjs/src/config.js +7 -7
  5. package/dist/cjs/src/config.js.map +1 -1
  6. package/dist/cjs/src/file-box.js +1 -1
  7. package/dist/cjs/src/file-box.js.map +1 -1
  8. package/dist/cjs/src/misc.d.ts.map +1 -1
  9. package/dist/cjs/src/misc.js +96 -85
  10. package/dist/cjs/src/misc.js.map +1 -1
  11. package/dist/cjs/src/misc.spec.js +6 -0
  12. package/dist/cjs/src/misc.spec.js.map +1 -1
  13. package/dist/cjs/src/version.js +1 -1
  14. package/dist/cjs/tests/chunk-download.spec.js +12 -56
  15. package/dist/cjs/tests/chunk-download.spec.js.map +1 -1
  16. package/dist/cjs/tests/misc-error-handling.spec.js +36 -26
  17. package/dist/cjs/tests/misc-error-handling.spec.js.map +1 -1
  18. package/dist/cjs/tests/network-timeout.spec.js +101 -118
  19. package/dist/cjs/tests/network-timeout.spec.js.map +1 -1
  20. package/dist/esm/src/config.d.ts +5 -4
  21. package/dist/esm/src/config.d.ts.map +1 -1
  22. package/dist/esm/src/config.js +6 -6
  23. package/dist/esm/src/config.js.map +1 -1
  24. package/dist/esm/src/file-box.js +2 -2
  25. package/dist/esm/src/file-box.js.map +1 -1
  26. package/dist/esm/src/misc.d.ts.map +1 -1
  27. package/dist/esm/src/misc.js +97 -86
  28. package/dist/esm/src/misc.js.map +1 -1
  29. package/dist/esm/src/misc.spec.js +6 -0
  30. package/dist/esm/src/misc.spec.js.map +1 -1
  31. package/dist/esm/src/version.js +1 -1
  32. package/dist/esm/tests/chunk-download.spec.js +12 -56
  33. package/dist/esm/tests/chunk-download.spec.js.map +1 -1
  34. package/dist/esm/tests/misc-error-handling.spec.js +36 -26
  35. package/dist/esm/tests/misc-error-handling.spec.js.map +1 -1
  36. package/dist/esm/tests/network-timeout.spec.js +103 -120
  37. package/dist/esm/tests/network-timeout.spec.js.map +1 -1
  38. package/package.json +1 -1
  39. package/src/config.ts +6 -9
  40. package/src/file-box.ts +2 -2
  41. package/src/misc.spec.ts +7 -0
  42. package/src/misc.ts +108 -89
  43. package/src/version.ts +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"network-timeout.spec.js","sourceRoot":"","sources":["../../../tests/network-timeout.spec.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"network-timeout.spec.js","sourceRoot":"","sources":["../../../tests/network-timeout.spec.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juzi/file-box",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "Pack a File into Box for easy move/transfer between servers no matter of where it is.(local path, remote url, or cloud storage)",
5
5
  "type": "module",
6
6
  "exports": {
package/src/config.ts CHANGED
@@ -1,12 +1,9 @@
1
1
  /// <reference path="./typings.d.ts" />
2
2
  export { VERSION } from './version.js'
3
3
 
4
- export const HTTP_REQUEST_TIMEOUT = Number(process.env['FILEBOX_HTTP_REQUEST_TIMEOUT'])
5
- || 10 * 1000
6
-
7
- export const HTTP_RESPONSE_TIMEOUT = Number(process.env['FILEBOX_HTTP_RESPONSE_TIMEOUT'] ?? process.env['FILEBOX_HTTP_TIMEOUT'])
8
- || 60 * 1000
9
-
10
- export const NO_SLICE_DOWN = process.env['FILEBOX_NO_SLICE_DOWN'] === 'true'
11
-
12
- export const READY_RETRY = Number(process.env['FILE_BOX_READY_RETRY']) || 3
4
+ // 导出可变配置对象,支持测试时动态修改
5
+ export const CONFIG = {
6
+ HTTP_REQUEST_TIMEOUT: Number(process.env['FILEBOX_HTTP_REQUEST_TIMEOUT']) || 10 * 1000,
7
+ HTTP_RESPONSE_TIMEOUT: Number(process.env['FILEBOX_HTTP_RESPONSE_TIMEOUT'] ?? process.env['FILEBOX_HTTP_TIMEOUT']) || 60 * 1000,
8
+ READY_RETRY: Number(process.env['FILEBOX_READY_RETRY'] ?? process.env['FILE_BOX_READY_RETRY']) || 3,
9
+ }
package/src/file-box.ts CHANGED
@@ -25,7 +25,7 @@ import {
25
25
  } from 'clone-class'
26
26
 
27
27
  import {
28
- READY_RETRY,
28
+ CONFIG,
29
29
  VERSION,
30
30
  } from './config.js'
31
31
  import {
@@ -637,7 +637,7 @@ class FileBox implements Pipeable, FileBoxInterface {
637
637
  break
638
638
  } catch (e) {
639
639
  tryCount++
640
- if (tryCount >= READY_RETRY) {
640
+ if (tryCount >= CONFIG.READY_RETRY) {
641
641
  throw e
642
642
  }
643
643
  }
package/src/misc.spec.ts CHANGED
@@ -5,6 +5,7 @@ import { createServer } from 'http'
5
5
  import type { AddressInfo } from 'net'
6
6
  import { test } from 'tstest'
7
7
 
8
+ import { CONFIG } from './config.js'
8
9
  import {
9
10
  dataUrlToBase64,
10
11
  httpHeaderToFileName,
@@ -13,6 +14,10 @@ import {
13
14
  streamToBuffer,
14
15
  } from './misc.js'
15
16
 
17
+ // 设置短超时用于测试
18
+ CONFIG.HTTP_REQUEST_TIMEOUT = 1000
19
+ CONFIG.HTTP_RESPONSE_TIMEOUT = 1000
20
+
16
21
  test('dataUrl to base64', async t => {
17
22
  const base64 = [
18
23
  'R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl',
@@ -97,6 +102,8 @@ test('httpStream', async t => {
97
102
  return
98
103
  }
99
104
 
105
+ // This server doesn't support Range, always return 200 with full content
106
+ // (ignoring any Range header)
100
107
  res.writeHead(200, {
101
108
  'Content-Length': String(content.length),
102
109
  'Content-Type': 'application/json',
package/src/misc.ts CHANGED
@@ -11,12 +11,10 @@ import { join } from 'path'
11
11
  import type { Readable } from 'stream'
12
12
  import { Transform } from 'stream'
13
13
  import { pipeline } from 'stream/promises'
14
+ import { setTimeout } from 'timers/promises'
14
15
  import { URL } from 'url'
15
16
 
16
- import {
17
- HTTP_REQUEST_TIMEOUT,
18
- HTTP_RESPONSE_TIMEOUT,
19
- } from './config.js'
17
+ import { CONFIG } from './config.js'
20
18
 
21
19
  const protocolMap: {
22
20
  [key: string]: { agent: http.Agent; request: typeof http.request }
@@ -28,6 +26,16 @@ const protocolMap: {
28
26
  const noop = () => { }
29
27
  const unsupportedRangeDomains = new Set<string>()
30
28
 
29
+ // 自定义 Error:标记需要回退到非分片下载
30
+ class FallbackError extends Error {
31
+
32
+ constructor (reason: string) {
33
+ super(`Fallback required: ${reason}`)
34
+ this.name = 'FallbackError'
35
+ }
36
+
37
+ }
38
+
31
39
  function getProtocol (protocol: string) {
32
40
  assert(protocolMap[protocol], new Error('unknown protocol: ' + protocol))
33
41
  return protocolMap[protocol]!
@@ -66,8 +74,6 @@ export async function httpHeadHeader (url: string, headers: http.OutgoingHttpHea
66
74
  return res.headers
67
75
  }
68
76
 
69
- // console.log('302 found for ' + url)
70
-
71
77
  if (!res.headers.location) {
72
78
  throw new Error('302 found but no location!')
73
79
  }
@@ -99,7 +105,7 @@ export async function httpStream (url: string, headers: http.OutgoingHttpHeaders
99
105
  if (headHeaders.location) {
100
106
  url = headHeaders.location
101
107
  }
102
- const { protocol, hostname } = new URL(url)
108
+ const { protocol, hostname, port } = new URL(url)
103
109
  getProtocol(protocol)
104
110
 
105
111
  const options: http.RequestOptions = {
@@ -107,19 +113,17 @@ export async function httpStream (url: string, headers: http.OutgoingHttpHeaders
107
113
  method: 'GET',
108
114
  }
109
115
 
110
- const fileSize = Number(headHeaders['content-length'])
111
-
112
- // 运行时读取 env:方便测试/调用方动态调整
113
- const noSliceDown = process.env['FILEBOX_NO_SLICE_DOWN'] === 'true'
114
-
115
- // 检查服务器是否支持 range 请求
116
- const supportsRange = headHeaders['accept-ranges'] === 'bytes'
117
-
118
- if (!unsupportedRangeDomains.has(hostname) && !noSliceDown && supportsRange && fileSize > 0) {
119
- return await downloadFileInChunks(url, options, proxyUrl)
120
- } else {
121
- return await fetch(url, options, proxyUrl)
122
- }
116
+ // 使用 hostname:port 作为域名标识,避免不同端口的服务互相影响
117
+ const defaultPort = protocol === 'https:' ? '443' : '80'
118
+ const hostKey = `${hostname}:${port || defaultPort}`
119
+
120
+ // 直接尝试分片下载,不检查 Accept-Ranges 和 fileSize
121
+ // 原因:
122
+ // 1. 有些服务器 HEAD 不返回 Accept-Ranges 但实际支持分片
123
+ // 2. 有些服务器 HEAD 返回 fileSize=0 但实际支持分片
124
+ // downloadFileInChunks 内部有完善的回退机制处理不支持的情况
125
+ const result = await downloadFileInChunks(url, options, proxyUrl, hostKey)
126
+ return result
123
127
  }
124
128
 
125
129
  async function fetch (url: string, options: http.RequestOptions, proxyUrl?: string): Promise<http.IncomingMessage> {
@@ -152,10 +156,10 @@ async function fetch (url: string, options: http.RequestOptions, proxyUrl?: stri
152
156
  req.off('error', noop)
153
157
  })
154
158
  // request timeout:只用于“拿到 response 之前”(连接/握手/首包)
155
- .setTimeout(HTTP_REQUEST_TIMEOUT, () => {
159
+ .setTimeout(CONFIG.HTTP_REQUEST_TIMEOUT, () => {
156
160
  // 已经拿到 response 时,不要再用 request timeout 误伤(会导致 aborted/ECONNRESET)
157
161
  if (res) return
158
- abortController.abort(new Error(`FileBox: Http request timeout (${HTTP_REQUEST_TIMEOUT})!`))
162
+ abortController.abort(new Error(`FileBox: Http request timeout (${CONFIG.HTTP_REQUEST_TIMEOUT})!`))
159
163
  })
160
164
  .end()
161
165
 
@@ -168,7 +172,6 @@ async function fetch (url: string, options: http.RequestOptions, proxyUrl?: stri
168
172
  res.on('error', noop)
169
173
  signal.throwIfAborted()
170
174
  } catch (e) {
171
- // once(...) 被 signal abort 时通常会抛 AbortError;优先抛出 abort(reason) 的真实原因
172
175
  const reason = signal.reason as unknown
173
176
  const err = reason instanceof Error
174
177
  ? reason
@@ -196,8 +199,8 @@ async function fetch (url: string, options: http.RequestOptions, proxyUrl?: stri
196
199
  signal.removeEventListener('abort', onAbort)
197
200
  res!.off('error', noop)
198
201
  })
199
- .setTimeout(HTTP_RESPONSE_TIMEOUT, () => {
200
- abortController.abort(new Error(`FileBox: Http response timeout (${HTTP_RESPONSE_TIMEOUT})!`))
202
+ .setTimeout(CONFIG.HTTP_RESPONSE_TIMEOUT, () => {
203
+ abortController.abort(new Error(`FileBox: Http response timeout (${CONFIG.HTTP_RESPONSE_TIMEOUT})!`))
201
204
  })
202
205
  return res!
203
206
  }
@@ -229,10 +232,11 @@ function createSkipTransform (skipBytes: number): Transform {
229
232
  async function downloadFileInChunks (
230
233
  url: string,
231
234
  options: http.RequestOptions,
232
- proxyUrl?: string,
235
+ proxyUrl: string | undefined,
236
+ hostname: string,
233
237
  ): Promise<Readable> {
234
238
  const tmpFile = join(tmpdir(), `filebox-${randomUUID()}`)
235
- const writeStream = createWriteStream(tmpFile)
239
+ let writeStream = createWriteStream(tmpFile)
236
240
  const writeAbortController = new AbortController()
237
241
  const signal = writeAbortController.signal
238
242
  const onWriteError = (err: unknown) => {
@@ -249,43 +253,42 @@ async function downloadFileInChunks (
249
253
  let start = 0
250
254
  let downSize = 0
251
255
  let retries = 3
252
- // 标识是否需要回退到非分片下载
253
- let shouldFallback = false
256
+ // 控制是否使用 Range 请求(根据域名黑名单初始化)
257
+ let useRange = !unsupportedRangeDomains.has(hostname)
258
+ let useChunked = false
254
259
 
255
260
  do {
256
261
  // 每次循环前检查文件实际大小,作为真实的下载进度
257
262
  // 这样在重试时可以从实际写入的位置继续,避免数据重复
258
- try {
259
- const fileStats = await stat(tmpFile)
260
- const actualSize = fileStats.size
261
- if (actualSize > downSize) {
262
- // 文件实际大小比记录的大,说明之前有部分写入
263
- downSize = actualSize
264
- start = actualSize
265
- }
266
- } catch (error) {
267
- // 文件不存在或无法访问,使用当前的 downSize
263
+ const fileStats = await stat(tmpFile).then(stats => stats.size).catch(() => 0)
264
+ if (fileStats !== downSize) {
265
+ // 文件实际大小与记录的不一致,使用实际大小
266
+ downSize = fileStats
267
+ start = fileStats
268
268
  }
269
269
 
270
- const range = `bytes=${start}-`
271
270
  const requestOptions = Object.assign({}, requestBaseOptions)
272
271
  assert(requestOptions.headers, 'Errors that should not happen: Invalid headers')
273
- ;(requestOptions.headers as http.OutgoingHttpHeaders)['Range'] = range
274
-
275
- // 每次请求创建独立的 AbortController 来管理当前请求的生命周期
276
- const requestAbortController = new AbortController()
277
- requestOptions.signal = requestAbortController.signal
272
+ const headers = requestOptions.headers as http.OutgoingHttpHeaders
273
+
274
+ // 根据 useRange flag 决定是否添加 Range header
275
+ if (useRange) {
276
+ const range = `bytes=${start}-`
277
+ headers['Range'] = range
278
+ } else {
279
+ delete headers['Range']
280
+ }
278
281
 
282
+ let res: http.IncomingMessage
279
283
  try {
280
- const res = await fetch(url, requestOptions, proxyUrl)
284
+ res = await fetch(url, requestOptions, proxyUrl)
281
285
  if (res.statusCode === 416) {
282
- // 某些云服务商对分片下载的支持可能不规范,需要保留一个回退的方式
283
- shouldFallback = true
284
- break
286
+ // 416: Range Not Satisfiable,服务器不支持此范围或文件大小不匹配
287
+ throw new FallbackError('416 Range Not Satisfiable')
285
288
  }
286
289
  assert(allowStatusCode.includes(res.statusCode ?? 0), `Request failed with status code ${res.statusCode}`)
287
- const contentLength = Number(res.headers['content-length'])
288
- assert(contentLength > 0, 'Server returned 0 bytes of data')
290
+ const contentLength = Number(res.headers['content-length']) || 0
291
+ assert(contentLength >= 0, `Server returned ${contentLength} bytes of data`)
289
292
 
290
293
  // 206: 部分内容,继续分片下载
291
294
  // 200: 完整内容,服务器不支持 range 或返回全部数据
@@ -294,8 +297,7 @@ async function downloadFileInChunks (
294
297
  const contentRange = res.headers['content-range']
295
298
  if (!contentRange) {
296
299
  // Content-Range 缺失,服务器不规范,回退到非分片下载
297
- shouldFallback = true
298
- break
300
+ throw new FallbackError('Missing Content-Range header')
299
301
  }
300
302
 
301
303
  let end: number
@@ -308,8 +310,7 @@ async function downloadFileInChunks (
308
310
  total = parsed.total
309
311
  } catch (error) {
310
312
  // Content-Range 格式错误,服务器不规范,回退到非分片下载
311
- shouldFallback = true
312
- break
313
+ throw new FallbackError(`Invalid Content-Range: ${contentRange}`)
313
314
  }
314
315
 
315
316
  if (expectedTotal === null) {
@@ -322,6 +323,9 @@ async function downloadFileInChunks (
322
323
  throw new Error(`File size mismatch: expected ${expectedTotal}, but server returned ${total}`)
323
324
  }
324
325
 
326
+ // 标记使用了分片下载
327
+ useChunked = true
328
+
325
329
  // 验证服务器返回的范围是否与请求匹配
326
330
  if (actualStart !== start) {
327
331
  if (actualStart > start) {
@@ -345,58 +349,73 @@ async function downloadFileInChunks (
345
349
  // end 是最后一个字节的索引,下次从 end+1 开始
346
350
  downSize += end - start + 1
347
351
  start = downSize
348
- } else {
349
- // 200: 服务器返回完整文件,不支持 range
350
- if (start > 0) {
351
- // 中途收到 200,服务器停止支持 range,标记并回退到普通下载
352
- shouldFallback = true
353
- break
352
+ } else if (res.statusCode === 200) {
353
+ // 200: 服务器返回完整文件
354
+ if (useChunked || start > 0) {
355
+ // 之前以分片模式下载过数据
356
+ writeStream.destroy()
357
+ await rm(tmpFile, { force: true }).catch(() => {})
358
+ writeStream = createWriteStream(tmpFile)
359
+ writeStream.on('error', onWriteError)
360
+ start = 0
361
+ downSize = 0
354
362
  }
355
- // 首次请求返回 200,正常处理
356
- await pipeline(res, writeStream, { signal })
363
+
364
+ // 处理完整文件响应
365
+ expectedTotal = contentLength
366
+ await pipeline(res, writeStream, { end: false, signal })
357
367
  downSize = contentLength
358
368
  break
369
+ } else {
370
+ throw new Error(`Unexpected status code: ${res.statusCode}`)
359
371
  }
360
372
  // 成功后重置重试次数
361
373
  retries = 3
362
374
  } catch (error) {
375
+ if (error instanceof FallbackError) {
376
+ // 回退逻辑:记录域名、重置状态,在下次循环中以非 range 模式请求
377
+ unsupportedRangeDomains.add(hostname)
378
+
379
+ // 关闭当前写入流
380
+ writeStream.destroy()
381
+ await rm(tmpFile, { force: true }).catch(() => {})
382
+
383
+ // 检查是否已经是非 Range 模式,避免无限回退
384
+ if (!useRange) {
385
+ // 已经是非 Range 模式还失败,无法继续
386
+ throw new Error(`Download failed even in non-chunked mode: ${(error as Error).message}`)
387
+ }
388
+
389
+ writeStream = createWriteStream(tmpFile)
390
+ writeStream.once('error', onWriteError)
391
+
392
+ // 重置所有状态
393
+ expectedTotal = null
394
+ downSize = 0
395
+ start = 0
396
+ useChunked = false
397
+ useRange = false
398
+ retries = 3
399
+ continue
400
+ }
401
+
402
+ // 普通错误:重试
363
403
  const err = error instanceof Error ? error : new Error(String(error))
364
404
  if (--retries <= 0) {
365
405
  writeStream.destroy()
366
- await rm(tmpFile, { force: true })
406
+ await rm(tmpFile, { force: true }).catch(() => {})
367
407
  throw new Error(`Download file with chunk failed! ${err.message}`, { cause: err })
368
408
  }
369
409
  // 失败后等待一小段时间再重试
370
- await new Promise(resolve => setTimeout(resolve, 100))
371
- } finally {
372
- // 确保请求被清理(成功时也需要 abort 以释放资源)
373
- requestAbortController.abort()
410
+ await setTimeout(100)
374
411
  }
375
412
  } while (expectedTotal === null || downSize < expectedTotal)
376
413
 
377
- // 统一处理回退到非分片下载的情况
378
- if (shouldFallback) {
379
- unsupportedRangeDomains.add(new URL(url).hostname)
380
- writeStream.destroy()
381
- try {
382
- await once(writeStream, 'close', { signal })
383
- } catch {}
384
- await rm(tmpFile, { force: true })
385
- return await fetch(url, requestBaseOptions, proxyUrl)
386
- }
387
-
388
- writeStream.end()
389
- try {
414
+ if (!writeStream.destroyed && !writeStream.writableFinished) {
415
+ writeStream.end()
390
416
  await once(writeStream, 'finish', { signal })
391
- } catch (e) {
392
- const reason = signal.reason as unknown
393
- if (reason instanceof Error) {
394
- throw reason
395
- }
396
- throw e
397
- } finally {
398
- writeStream.off('error', onWriteError)
399
417
  }
418
+ writeStream.off('error', onWriteError)
400
419
 
401
420
  const readStream = createReadStream(tmpFile)
402
421
  readStream.once('close', () => {
package/src/version.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  /**
2
2
  * This file was auto generated from scripts/generate-version.sh
3
3
  */
4
- export const VERSION: string = '1.8.0'
4
+ export const VERSION: string = '1.8.1'