1
1
import { StreamCollector } from "@smithy/types" ;
2
+ import { fromBase64 } from "@smithy/util-base64" ;
2
3
3
4
export const streamCollector : StreamCollector = async ( stream : Blob | ReadableStream ) : Promise < Uint8Array > => {
4
5
if ( ( typeof Blob === "function" && stream instanceof Blob ) || stream . constructor ?. name === "Blob" ) {
5
- return new Uint8Array ( await ( stream as Blob ) . arrayBuffer ( ) ) ;
6
+ if ( Blob . prototype . arrayBuffer !== undefined ) {
7
+ return new Uint8Array ( await ( stream as Blob ) . arrayBuffer ( ) ) ;
8
+ }
9
+ return collectBlob ( stream as Blob ) ;
6
10
}
7
11
8
12
return collectStream ( stream as ReadableStream ) ;
9
13
} ;
10
14
15
+ async function collectBlob ( blob : Blob ) : Promise < Uint8Array > {
16
+ const base64 = await readToBase64 ( blob ) ;
17
+ const arrayBuffer = fromBase64 ( base64 ) ;
18
+ return new Uint8Array ( arrayBuffer ) ;
19
+ }
20
+
11
21
async function collectStream ( stream : ReadableStream ) : Promise < Uint8Array > {
12
22
const chunks = [ ] ;
13
23
const reader = stream . getReader ( ) ;
@@ -32,3 +42,26 @@ async function collectStream(stream: ReadableStream): Promise<Uint8Array> {
32
42
33
43
return collected ;
34
44
}
45
+
46
+ function readToBase64 ( blob : Blob ) : Promise < string > {
47
+ return new Promise ( ( resolve , reject ) => {
48
+ const reader = new FileReader ( ) ;
49
+ reader . onloadend = ( ) => {
50
+ // reference: https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL
51
+ // response from readAsDataURL is always prepended with "data:*/*;base64,"
52
+ if ( reader . readyState !== 2 ) {
53
+ return reject ( new Error ( "Reader aborted too early" ) ) ;
54
+ }
55
+ const result = ( reader . result ?? "" ) as string ;
56
+ // Response can include only 'data:' for empty blob, return empty string in this case.
57
+ // Otherwise, return the string after ','
58
+ const commaIndex = result . indexOf ( "," ) ;
59
+ const dataOffset = commaIndex > - 1 ? commaIndex + 1 : result . length ;
60
+ resolve ( result . substring ( dataOffset ) ) ;
61
+ } ;
62
+ reader . onabort = ( ) => reject ( new Error ( "Read aborted" ) ) ;
63
+ reader . onerror = ( ) => reject ( reader . error ) ;
64
+ // reader.readAsArrayBuffer is not always available
65
+ reader . readAsDataURL ( blob ) ;
66
+ } ) ;
67
+ }
0 commit comments