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