1
1
/*!
2
- * qiniu-js-sdk v1.0.16.1 -beta
2
+ * qiniu-js-sdk v1.0.17 -beta
3
3
*
4
4
* Copyright 2015 by Qiniu
5
5
* Released under GPL V2 License.
6
6
*
7
7
* GitHub: http://github.com/qiniu/js-sdk
8
8
*
9
- * Date: 2016-7 -12
9
+ * Date: 2016-9 -12
10
10
*/
11
11
12
12
/*global plupload ,mOxie*/
@@ -160,6 +160,16 @@ function QiniuJsSDK() {
160
160
"http://up.qiniu.com"
161
161
] ;
162
162
163
+ var qiniuUpHosts = {
164
+ "http" : [
165
+ "http://upload.qiniu.com" ,
166
+ "http://up.qiniu.com"
167
+ ] ,
168
+ "https" : [
169
+ "https://up.qbox.me"
170
+ ]
171
+ } ;
172
+
163
173
var changeUrlTimes = 0 ;
164
174
165
175
/**
@@ -170,17 +180,14 @@ function QiniuJsSDK() {
170
180
* it will set 'qiniuUploadUrl' value with 'qiniuUploadUrls' looply
171
181
*/
172
182
this . resetUploadUrl = function ( ) {
173
- if ( window . location . protocol === 'https:' ) {
174
- qiniuUploadUrl = 'https://up.qbox.me' ;
175
- } else {
176
- var i = changeUrlTimes % qiniuUploadUrls . length ;
177
- qiniuUploadUrl = qiniuUploadUrls [ i ] ;
178
- changeUrlTimes ++ ;
179
- }
180
- logger . debug ( 'resetUploadUrl: ' + qiniuUploadUrl ) ;
183
+ var hosts = window . location . protocol === 'https:' ? qiniuUpHosts . https : qiniuUpHosts . http ;
184
+ var i = changeUrlTimes % hosts . length ;
185
+ qiniuUploadUrl = hosts [ i ] ;
186
+ changeUrlTimes ++ ;
187
+ logger . debug ( 'resetUploadUrl: ' + qiniuUploadUrl ) ;
181
188
} ;
182
189
183
- this . resetUploadUrl ( ) ;
190
+ // this.resetUploadUrl();
184
191
185
192
186
193
/**
@@ -286,6 +293,62 @@ function QiniuJsSDK() {
286
293
return utftext ;
287
294
} ;
288
295
296
+ this . base64_decode = function ( data ) {
297
+ // http://kevin.vanzonneveld.net
298
+ // + original by: Tyler Akins (http://rumkin.com)
299
+ // + improved by: Thunder.m
300
+ // + input by: Aman Gupta
301
+ // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
302
+ // + bugfixed by: Onno Marsman
303
+ // + bugfixed by: Pellentesque Malesuada
304
+ // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
305
+ // + input by: Brett Zamir (http://brett-zamir.me)
306
+ // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
307
+ // * example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==');
308
+ // * returns 1: 'Kevin van Zonneveld'
309
+ // mozilla has this native
310
+ // - but breaks in 2.0.0.12!
311
+ //if (typeof this.window['atob'] == 'function') {
312
+ // return atob(data);
313
+ //}
314
+ var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" ;
315
+ var o1 , o2 , o3 , h1 , h2 , h3 , h4 , bits , i = 0 ,
316
+ ac = 0 ,
317
+ dec = "" ,
318
+ tmp_arr = [ ] ;
319
+
320
+ if ( ! data ) {
321
+ return data ;
322
+ }
323
+
324
+ data += '' ;
325
+
326
+ do { // unpack four hexets into three octets using index points in b64
327
+ h1 = b64 . indexOf ( data . charAt ( i ++ ) ) ;
328
+ h2 = b64 . indexOf ( data . charAt ( i ++ ) ) ;
329
+ h3 = b64 . indexOf ( data . charAt ( i ++ ) ) ;
330
+ h4 = b64 . indexOf ( data . charAt ( i ++ ) ) ;
331
+
332
+ bits = h1 << 18 | h2 << 12 | h3 << 6 | h4 ;
333
+
334
+ o1 = bits >> 16 & 0xff ;
335
+ o2 = bits >> 8 & 0xff ;
336
+ o3 = bits & 0xff ;
337
+
338
+ if ( h3 === 64 ) {
339
+ tmp_arr [ ac ++ ] = String . fromCharCode ( o1 ) ;
340
+ } else if ( h4 === 64 ) {
341
+ tmp_arr [ ac ++ ] = String . fromCharCode ( o1 , o2 ) ;
342
+ } else {
343
+ tmp_arr [ ac ++ ] = String . fromCharCode ( o1 , o2 , o3 ) ;
344
+ }
345
+ } while ( i < data . length ) ;
346
+
347
+ dec = tmp_arr . join ( '' ) ;
348
+
349
+ return dec ;
350
+ } ;
351
+
289
352
/**
290
353
* encode data by base64
291
354
* @param {String } data to encode
@@ -359,6 +422,11 @@ function QiniuJsSDK() {
359
422
return v . replace ( / \/ / g, '_' ) . replace ( / \+ / g, '-' ) ;
360
423
} ;
361
424
425
+ this . URLSafeBase64Decode = function ( v ) {
426
+ v = v . replace ( / _ / g, '/' ) . replace ( / - / g, '+' ) ;
427
+ return this . base64_decode ( v ) ;
428
+ } ;
429
+
362
430
// TODO: use mOxie
363
431
/**
364
432
* craete object used to AJAX
@@ -514,15 +582,58 @@ function QiniuJsSDK() {
514
582
// if op.chunk_size set 0 will be cause to direct upload
515
583
} ;
516
584
517
- // getUptoken maybe called at Init Event or BeforeUpload Event
585
+ var getHosts = function ( hosts ) {
586
+ var result = [ ] ;
587
+ for ( var i = 0 ; i < hosts . length ; i ++ ) {
588
+ var host = hosts [ i ] ;
589
+ if ( host . indexOf ( '-H' ) === 0 ) {
590
+ result . push ( host . split ( ' ' ) [ 2 ] ) ;
591
+ } else {
592
+ result . push ( host ) ;
593
+ }
594
+ }
595
+ return result ;
596
+ } ;
597
+
598
+ var getUpHosts = function ( uptoken ) {
599
+ var segments = uptoken . split ( ":" ) ;
600
+ var ak = segments [ 0 ] ;
601
+ var putPolicy = that . parseJSON ( that . URLSafeBase64Decode ( segments [ 2 ] ) ) ;
602
+ var uphosts_url = "https://uc.qbox.me/v1/query?ak=" + ak + "&bucket=" + putPolicy . scope ;
603
+ logger . debug ( "ak: " , ak ) ;
604
+ logger . debug ( "putPolicy: " , putPolicy ) ;
605
+ logger . debug ( "get uphosts from: " , uphosts_url ) ;
606
+ var ajax = that . createAjax ( ) ;
607
+ ajax . open ( 'GET' , uphosts_url , false ) ;
608
+ ajax . send ( ) ;
609
+ if ( ajax . status === 200 ) {
610
+ var res = that . parseJSON ( ajax . responseText ) ;
611
+ qiniuUpHosts . http = getHosts ( res . http . up ) ;
612
+ qiniuUpHosts . https = getHosts ( res . https . up ) ;
613
+ logger . debug ( "get new uphosts: " , qiniuUpHosts ) ;
614
+ that . resetUploadUrl ( ) ;
615
+ } else {
616
+ logger . error ( "get uphosts error: " , ajax . responseText ) ;
617
+ }
618
+ return ;
619
+ } ;
620
+
621
+ var getUptoken = function ( file ) {
622
+ if ( ! that . token || that . tokenInfo . isExpired ( ) ) {
623
+ return getNewUpToken ( file ) ;
624
+ } else {
625
+ return that . token ;
626
+ }
627
+ } ;
628
+
629
+ // getNewUptoken maybe called at Init Event or BeforeUpload Event
518
630
// case Init Event, the file param of getUptken will be set a null value
519
631
// if op.uptoken has value, set uptoken with op.uptoken
520
632
// else if op.uptoken_url has value, set uptoken from op.uptoken_url
521
633
// else if op.uptoken_func has value, set uptoken by result of op.uptoken_func
522
- var getUpToken = function ( file ) {
634
+ var getNewUpToken = function ( file ) {
523
635
if ( op . uptoken ) {
524
636
that . token = op . uptoken ;
525
- return ;
526
637
} else if ( op . uptoken_url ) {
527
638
logger . debug ( "get uptoken from: " , that . uptoken_url ) ;
528
639
// TODO: use mOxie
@@ -539,19 +650,40 @@ function QiniuJsSDK() {
539
650
if ( ajax . status === 200 ) {
540
651
var res = that . parseJSON ( ajax . responseText ) ;
541
652
that . token = res . uptoken ;
542
- logger . debug ( "get new uptoken: " , res . uptoken ) ;
653
+ var segments = that . token . split ( ":" ) ;
654
+ var putPolicy = that . parseJSON ( that . URLSafeBase64Decode ( segments [ 2 ] ) ) ;
655
+ if ( ! that . tokenMap ) {
656
+ that . tokenMap = { } ;
657
+ }
658
+ var getTimestamp = function ( time ) {
659
+ return Math . ceil ( time . getTime ( ) / 1000 ) ;
660
+ } ;
661
+ var serverTime = getTimestamp ( new Date ( ajax . getResponseHeader ( "date" ) ) ) ;
662
+ var clientTime = getTimestamp ( new Date ( ) ) ;
663
+ that . tokenInfo = {
664
+ serverDelay : clientTime - serverTime ,
665
+ deadline : putPolicy . deadline ,
666
+ isExpired : function ( ) {
667
+ var leftTime = this . deadline - getTimestamp ( new Date ( ) ) + this . serverDelay ;
668
+ return leftTime < 600 ;
669
+ }
670
+ } ;
671
+ logger . debug ( "get new uptoken: " , that . token ) ;
672
+ logger . debug ( "get token info: " , that . tokenInfo ) ;
543
673
} else {
544
674
logger . error ( "get uptoken error: " , ajax . responseText ) ;
545
675
}
546
- return ;
547
676
} else if ( op . uptoken_func ) {
548
677
logger . debug ( "get uptoken from uptoken_func" ) ;
549
678
that . token = op . uptoken_func ( file ) ;
550
679
logger . debug ( "get new uptoken: " , that . token ) ;
551
- return ;
552
680
} else {
553
681
logger . error ( "one of [uptoken, uptoken_url, uptoken_func] settings in options is required!" ) ;
554
682
}
683
+ if ( that . token ) {
684
+ getUpHosts ( that . token ) ;
685
+ }
686
+ return that . token ;
555
687
} ;
556
688
557
689
// get file key according with the user passed options
@@ -650,17 +782,17 @@ function QiniuJsSDK() {
650
782
651
783
logger . debug ( "new plupload.Uploader(option)" ) ;
652
784
653
- // bind getUpToken to 'Init' event
785
+ // bind getNewUpToken to 'Init' event
654
786
uploader . bind ( 'Init' , function ( up , params ) {
655
787
logger . debug ( "Init event activated" ) ;
656
788
// if op.get_new_uptoken is not true
657
- // invoke getUptoken when uploader init
789
+ // invoke getNewUptoken when uploader init
658
790
// else
659
- // getUptoken everytime before a new file upload
791
+ // getNewUptoken everytime before a new file upload
660
792
if ( ! op . get_new_uptoken ) {
661
- getUpToken ( null ) ;
793
+ getNewUpToken ( null ) ;
662
794
}
663
- //getUpToken (null);
795
+ //getNewUpToken (null);
664
796
} ) ;
665
797
666
798
logger . debug ( "bind Init event" ) ;
@@ -722,7 +854,7 @@ function QiniuJsSDK() {
722
854
ctx = '' ;
723
855
724
856
if ( op . get_new_uptoken ) {
725
- getUpToken ( file ) ;
857
+ getNewUpToken ( file ) ;
726
858
}
727
859
728
860
var directUpload = function ( up , file , func ) {
@@ -859,7 +991,7 @@ function QiniuJsSDK() {
859
991
'chunk_size' : chunk_size ,
860
992
'required_features' : "chunks" ,
861
993
'headers' : {
862
- 'Authorization' : 'UpToken ' + that . token
994
+ 'Authorization' : 'UpToken ' + getUptoken ( file )
863
995
} ,
864
996
'multipart_params' : multipart_params_obj
865
997
} ) ;
@@ -907,6 +1039,11 @@ function QiniuJsSDK() {
907
1039
} ) ;
908
1040
logger . debug ( "up.setOption url: " , qiniuUploadUrl + '/mkblk/' + leftSize ) ;
909
1041
}
1042
+ up . setOption ( {
1043
+ 'headers' : {
1044
+ 'Authorization' : 'UpToken ' + getUptoken ( file )
1045
+ }
1046
+ } ) ;
910
1047
localStorage . setItem ( file . name , that . stringifyJSON ( {
911
1048
ctx : ctx ,
912
1049
percent : file . percent ,
0 commit comments