11import { StreamCollector } from "@smithy/types" ;
2+ import { fromBase64 } from "@smithy/util-base64" ;
23
34export const streamCollector : StreamCollector = async ( stream : Blob | ReadableStream ) : Promise < Uint8Array > => {
45 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 ) ;
610 }
711
812 return collectStream ( stream as ReadableStream ) ;
913} ;
1014
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+
1121async function collectStream ( stream : ReadableStream ) : Promise < Uint8Array > {
1222 const chunks = [ ] ;
1323 const reader = stream . getReader ( ) ;
@@ -32,3 +42,26 @@ async function collectStream(stream: ReadableStream): Promise<Uint8Array> {
3242
3343 return collected ;
3444}
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