1+ /* BlobBuilder.js
2+ * A BlobBuilder implementation.
3+ * 2012-04-21
4+ *
5+ * By Eli Grey, http://eligrey.com
6+ * License: X11/MIT
7+ * See LICENSE.md
8+ */
9+
10+ /*global self, unescape */
11+ /*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
12+ plusplus: true */
13+
14+ /*! @source http://purl.eligrey.com/github/BlobBuilder.js/blob/master/BlobBuilder.js */
15+
16+ var BlobBuilder = BlobBuilder || self . WebKitBlobBuilder || self . MozBlobBuilder || self . MSBlobBuilder || ( function ( view ) {
17+ "use strict" ;
18+ var
19+ get_class = function ( object ) {
20+ return Object . prototype . toString . call ( object ) . match ( / ^ \[ o b j e c t \s ( .* ) \] $ / ) [ 1 ] ;
21+ }
22+ , FakeBlobBuilder = function ( ) {
23+ this . data = [ ] ;
24+ }
25+ , FakeBlob = function ( data , type , encoding ) {
26+ this . data = data ;
27+ this . size = data . length ;
28+ this . type = type ;
29+ this . encoding = encoding ;
30+ }
31+ , FBB_proto = FakeBlobBuilder . prototype
32+ , FB_proto = FakeBlob . prototype
33+ , FileReaderSync = view . FileReaderSync
34+ , FileException = function ( type ) {
35+ this . code = this [ this . name = type ] ;
36+ }
37+ , file_ex_codes = (
38+ "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR "
39+ + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR"
40+ ) . split ( " " )
41+ , file_ex_code = file_ex_codes . length
42+ , realURL = view . URL || view . webkitURL || view
43+ , real_create_object_URL = realURL . createObjectURL
44+ , real_revoke_object_URL = realURL . revokeObjectURL
45+ , URL = realURL
46+ , btoa = view . btoa
47+ , atob = view . atob
48+ , can_apply_typed_arrays = false
49+ , can_apply_typed_arrays_test = function ( pass ) {
50+ can_apply_typed_arrays = ! pass ;
51+ }
52+
53+ , ArrayBuffer = view . ArrayBuffer
54+ , Uint8Array = view . Uint8Array
55+ ;
56+ FakeBlobBuilder . fake = FB_proto . fake = true ;
57+ while ( file_ex_code -- ) {
58+ FileException . prototype [ file_ex_codes [ file_ex_code ] ] = file_ex_code + 1 ;
59+ }
60+ try {
61+ if ( Uint8Array ) {
62+ can_apply_typed_arrays_test . apply ( 0 , new Uint8Array ( 1 ) ) ;
63+ }
64+ } catch ( ex ) { }
65+ if ( ! realURL . createObjectURL ) {
66+ URL = view . URL = { } ;
67+ }
68+ URL . createObjectURL = function ( blob ) {
69+ var
70+ type = blob . type
71+ , data_URI_header
72+ ;
73+ if ( type === null ) {
74+ type = "application/octet-stream" ;
75+ }
76+ if ( blob instanceof FakeBlob ) {
77+ data_URI_header = "data:" + type ;
78+ if ( blob . encoding === "base64" ) {
79+ return data_URI_header + ";base64," + blob . data ;
80+ } else if ( blob . encoding === "URI" ) {
81+ return data_URI_header + "," + decodeURIComponent ( blob . data ) ;
82+ } if ( btoa ) {
83+ return data_URI_header + ";base64," + btoa ( blob . data ) ;
84+ } else {
85+ return data_URI_header + "," + encodeURIComponent ( blob . data ) ;
86+ }
87+ } else if ( real_create_object_url ) {
88+ return real_create_object_url . call ( realURL , blob ) ;
89+ }
90+ } ;
91+ URL . revokeObjectURL = function ( object_url ) {
92+ if ( object_url . substring ( 0 , 5 ) !== "data:" && real_revoke_object_url ) {
93+ real_revoke_object_url . call ( realURL , object_url ) ;
94+ }
95+ } ;
96+ FBB_proto . append = function ( data /*, endings*/ ) {
97+ var bb = this . data ;
98+ // decode data to a binary string
99+ if ( Uint8Array && data instanceof ArrayBuffer ) {
100+ if ( can_apply_typed_arrays ) {
101+ bb . push ( String . fromCharCode . apply ( String , new Uint8Array ( data ) ) ) ;
102+ } else {
103+ var
104+ str = ""
105+ , buf = new Uint8Array ( data )
106+ , i = 0
107+ , buf_len = buf . length
108+ ;
109+ for ( ; i < buf_len ; i ++ ) {
110+ str += String . fromCharCode ( buf [ i ] ) ;
111+ }
112+ }
113+ } else if ( get_class ( data ) === "Blob" || get_class ( data ) === "File" ) {
114+ if ( FileReaderSync ) {
115+ var fr = new FileReaderSync ;
116+ bb . push ( fr . readAsBinaryString ( data ) ) ;
117+ } else {
118+ // async FileReader won't work as BlobBuilder is sync
119+ throw new FileException ( "NOT_READABLE_ERR" ) ;
120+ }
121+ } else if ( data instanceof FakeBlob ) {
122+ if ( data . encoding === "base64" && atob ) {
123+ bb . push ( atob ( data . data ) ) ;
124+ } else if ( data . encoding === "URI" ) {
125+ bb . push ( decodeURIComponent ( data . data ) ) ;
126+ } else if ( data . encoding === "raw" ) {
127+ bb . push ( data . data ) ;
128+ }
129+ } else {
130+ if ( typeof data !== "string" ) {
131+ data += "" ; // convert unsupported types to strings
132+ }
133+ // decode UTF-16 to binary string
134+ bb . push ( unescape ( encodeURIComponent ( data ) ) ) ;
135+ }
136+ } ;
137+ FBB_proto . getBlob = function ( type ) {
138+ if ( ! arguments . length ) {
139+ type = null ;
140+ }
141+ return new FakeBlob ( this . data . join ( "" ) , type , "raw" ) ;
142+ } ;
143+ FBB_proto . toString = function ( ) {
144+ return "[object BlobBuilder]" ;
145+ } ;
146+ FB_proto . slice = function ( start , end , type ) {
147+ var args = arguments . length ;
148+ if ( args < 3 ) {
149+ type = null ;
150+ }
151+ return new FakeBlob (
152+ this . data . slice ( start , args > 1 ? end : this . data . length )
153+ , type
154+ , this . encoding
155+ ) ;
156+ } ;
157+ FB_proto . toString = function ( ) {
158+ return "[object Blob]" ;
159+ } ;
160+ return FakeBlobBuilder ;
161+ } ( self ) ) ;
0 commit comments