11declare let self : ServiceWorkerGlobalScope ;
2- import type { BufferType } from "../../types/client" ;
3- import { HEADER_KEY } from "../../types/worker" ;
4- import { destructureChunk } from "../utils/binary" ;
2+ import type { MessageType } from "../../types/worker" ;
3+ import { HEADER_KEY , MESSAGE_TYPE } from "../../types/worker" ;
54
65self . addEventListener ( "install" , ( ) => {
76 // 跳过等待 直接激活
@@ -15,24 +14,26 @@ self.addEventListener("activate", event => {
1514 console . log ( "Service Worker Activate" ) ;
1615} ) ;
1716
18- type StreamTuple = [ ReadableStream , ReadableStreamDefaultController < BufferType > , number ] ;
17+ type StreamTuple = [ ReadableStream < Uint8Array > ] ;
1918const map = new Map < string , StreamTuple > ( ) ;
2019
2120self . onmessage = event => {
22- const data = < BufferType > event . data ;
23- destructureChunk ( data ) . then ( ( { id, series, data } ) => {
24- const stream = map . get ( id ) ;
25- if ( ! stream ) return void 0 ;
26- const [ , controller , size ] = stream ;
27- // 需要处理 BackPressure 而 TransformStream 解决了问题
28- // 不能直接写入 ArrayBuffer 必须要写入 TypedArray 类型
29- controller . enqueue ( new Uint8Array ( data ) ) ;
30- // 数据块序列号 [0, TOTAL)
31- if ( series === size - 1 ) {
32- controller . close ( ) ;
21+ const port = event . ports [ 0 ] ;
22+ if ( ! port ) return void 0 ;
23+ port . onmessage = event => {
24+ const payload = event . data as MessageType ;
25+ if ( ! payload ) return void 0 ;
26+ if ( payload . key === MESSAGE_TYPE . TRANSFER_START ) {
27+ // 直接使用 ReadableStream 需要处理 BackPressure 而 TransformStream 解决了问题
28+ // controller.enqueue 不能直接写入 ArrayBuffer 必须要写入 TypedArray 类型
29+ const { id, readable } = payload ;
30+ map . set ( id , [ readable ] ) ;
31+ }
32+ if ( payload . key === MESSAGE_TYPE . TRANSFER_CLOSE ) {
33+ const { id } = payload ;
3334 map . delete ( id ) ;
3435 }
35- } ) ;
36+ } ;
3637} ;
3738
3839self . onfetch = event => {
@@ -42,35 +43,30 @@ self.onfetch = event => {
4243 const fileName = search . get ( HEADER_KEY . FILE_NAME ) ;
4344 const fileSize = search . get ( HEADER_KEY . FILE_SIZE ) ;
4445 const fileTotal = search . get ( HEADER_KEY . FILE_TOTAL ) ;
45- if ( fileId && fileName && fileSize && fileTotal ) {
46- const newFileName = decodeURIComponent ( fileName ) ;
47- let controller : ReadableStreamDefaultController | null = null ;
48- const readable = new ReadableStream ( {
49- start ( ctr ) {
50- controller = ctr ;
51- } ,
52- cancel ( reason ) {
53- console . log ( "ReadableStream Aborted" , reason ) ;
54- } ,
55- } ) ;
56- map . set ( fileId , [ readable , controller ! , Number ( fileTotal ) ] ) ;
57- const responseHeader = new Headers ( {
58- [ HEADER_KEY . FILE_ID ] : fileId ,
59- [ HEADER_KEY . FILE_SIZE ] : fileSize ,
60- [ HEADER_KEY . FILE_NAME ] : newFileName ,
61- "Content-Type" : "application/octet-stream; charset=utf-8" ,
62- "Content-Security-Policy" : "default-src 'none'" ,
63- "X-Content-Security-Policy" : "default-src 'none'" ,
64- "X-WebKit-CSP" : "default-src 'none'" ,
65- "X-XSS-Protection" : "1; mode=block" ,
66- "Cross-Origin-Embedder-Policy" : "require-corp" ,
67- "Content-Disposition" : "attachment; filename*=UTF-8''" + newFileName ,
68- "Content-Length" : fileSize ,
69- } ) ;
70- const response = new Response ( readable , {
71- headers : responseHeader ,
72- } ) ;
73- return event . respondWith ( response ) ;
46+ if ( ! fileId || ! fileName || ! fileSize || ! fileTotal ) {
47+ return fetch ( event . request ) ;
48+ }
49+ const transfer = map . get ( fileId ) ;
50+ if ( ! transfer ) {
51+ return null ;
7452 }
75- return fetch ( event . request ) ;
53+ const [ readable ] = transfer ;
54+ const newFileName = decodeURIComponent ( fileName ) ;
55+ const responseHeader = new Headers ( {
56+ [ HEADER_KEY . FILE_ID ] : fileId ,
57+ [ HEADER_KEY . FILE_SIZE ] : fileSize ,
58+ [ HEADER_KEY . FILE_NAME ] : newFileName ,
59+ "Content-Type" : "application/octet-stream; charset=utf-8" ,
60+ "Content-Security-Policy" : "default-src 'none'" ,
61+ "X-Content-Security-Policy" : "default-src 'none'" ,
62+ "X-WebKit-CSP" : "default-src 'none'" ,
63+ "X-XSS-Protection" : "1; mode=block" ,
64+ "Cross-Origin-Embedder-Policy" : "require-corp" ,
65+ "Content-Disposition" : "attachment; filename*=UTF-8''" + newFileName ,
66+ "Content-Length" : fileSize ,
67+ } ) ;
68+ const response = new Response ( readable , {
69+ headers : responseHeader ,
70+ } ) ;
71+ return event . respondWith ( response ) ;
7672} ;
0 commit comments