@@ -5,77 +5,7 @@ import './App.css';
5
5
import { type Chunker , type Source , OpenTDF } from '@opentdf/sdk' ;
6
6
import { type SessionInformation , OidcClient } from './session.js' ;
7
7
import { c } from './config.js' ;
8
-
9
- /**
10
- * Downloads a ReadableStream as a file by collecting its data and triggering a browser download.
11
- * Supports aborting via AbortSignal in options.
12
- *
13
- * @param stream - The ReadableStream of Uint8Array data to download as a file.
14
- * @param filename - The name for the downloaded file (default: 'download.tdf').
15
- * @param options - Optional StreamPipeOptions, supports AbortSignal for cancellation.
16
- * @returns Promise that resolves when the download is triggered or rejects if aborted.
17
- */
18
- export async function toFile (
19
- stream : ReadableStream < Uint8Array > ,
20
- filename = 'download.tdf' ,
21
- options ?: StreamPipeOptions
22
- ) : Promise < void > {
23
- // Get a reader for the stream
24
- const reader = stream . getReader ( ) ;
25
- const chunks : Uint8Array [ ] = [ ] ;
26
- let done = false ;
27
- let aborted = false ;
28
- const signal = options ?. signal ;
29
- let abortHandler : ( ( ) => void ) | undefined ;
30
-
31
- // Setup abort handling if a signal is provided
32
- if ( signal ) {
33
- if ( signal . aborted ) {
34
- throw new DOMException ( 'Aborted' , 'AbortError' ) ;
35
- }
36
- abortHandler = ( ) => {
37
- aborted = true ;
38
- reader . cancel ( ) ;
39
- } ;
40
- signal . addEventListener ( 'abort' , abortHandler ) ;
41
- }
42
- try {
43
- // Read the stream chunk by chunk
44
- while ( ! done ) {
45
- if ( aborted ) {
46
- throw new DOMException ( 'Aborted' , 'AbortError' ) ;
47
- }
48
- const { value, done : streamDone } = await reader . read ( ) ;
49
- if ( value ) {
50
- chunks . push ( value ) ; // Collect each chunk
51
- }
52
- done = streamDone ;
53
- }
54
- } finally {
55
- // Clean up abort event listener
56
- if ( signal && abortHandler ) {
57
- signal . removeEventListener ( 'abort' , abortHandler ) ;
58
- }
59
- }
60
- if ( aborted ) {
61
- throw new DOMException ( 'Aborted' , 'AbortError' ) ;
62
- }
63
- // Create a Blob from the collected chunks
64
- const blob = new Blob ( chunks ) ;
65
- // Create a temporary object URL for the Blob
66
- const url = URL . createObjectURL ( blob ) ;
67
- // Create an anchor element and trigger the download
68
- const a = document . createElement ( 'a' ) ;
69
- a . href = url ;
70
- a . download = filename ;
71
- document . body . appendChild ( a ) ;
72
- a . click ( ) ;
73
- // Clean up the anchor and object URL after download is triggered
74
- setTimeout ( ( ) => {
75
- document . body . removeChild ( a ) ;
76
- URL . revokeObjectURL ( url ) ;
77
- } , 0 ) ;
78
- }
8
+ import { downloadReadableStream } from './utils/download-readable-stream' ;
79
9
80
10
function decryptedFileName ( encryptedFileName : string ) : string {
81
11
// Groups: 1 file 'name' bit
@@ -450,7 +380,7 @@ function App() {
450
380
try {
451
381
switch ( sinkType ) {
452
382
case 'file' :
453
- await toFile ( cipherTextWithProgress , downloadName , { signal : sc . signal } ) ;
383
+ await downloadReadableStream ( cipherTextWithProgress , downloadName , { signal : sc . signal } ) ;
454
384
break ;
455
385
case 'fsapi' :
456
386
if ( ! f ) {
@@ -525,7 +455,7 @@ function App() {
525
455
. pipeThrough ( progressTransformers . writer ) ;
526
456
switch ( sinkType ) {
527
457
case 'file' :
528
- await toFile ( plainTextStream , dfn , { signal : sc . signal } ) ;
458
+ await downloadReadableStream ( plainTextStream , dfn , { signal : sc . signal } ) ;
529
459
break ;
530
460
case 'fsapi' :
531
461
if ( ! f ) {
0 commit comments