-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
2391 lines (1910 loc) · 161 KB
/
Copy pathatom.xml
File metadata and controls
2391 lines (1910 loc) · 161 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[Code Infinity]]></title>
<link href="http://www.orcame.com/atom.xml" rel="self"/>
<link href="http://www.orcame.com/"/>
<updated>2014-01-15T20:11:56+08:00</updated>
<id>http://www.orcame.com/</id>
<author>
<name><![CDATA[orcame]]></name>
<email><![CDATA[orcame@outlook.com]]></email>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[又折腾Linux系统]]></title>
<link href="http://www.orcame.com/blog/2014/01/13/after-install-ubuntu/"/>
<updated>2014-01-13T20:42:00+08:00</updated>
<id>http://www.orcame.com/blog/2014/01/13/after-install-ubuntu</id>
<content type="html"><![CDATA[<p>最近手痒,mint主题换过之后总是各种问题不断,换回默认的主题又看着那些个方块疙瘩图标实在是碍眼,终于忍不住动手了。</p>
<h2>Fedora</h2>
<p>先是安装了fedora,fedora(gnome)界面简简单单,是我喜欢的风格,只是那个terminal不能背景透明真是很坑爹的(这个要怪gnome的),非常不方便。<br/>
先来说说broadcom驱动的安装,网上有很多这个教程,均以失败告终。还是官方的比较靠谱,找到这个<a href="http://zh-cn.broadcom.com/support/802.11/linux_sta.php">下载链接</a>,安装方法在README里面。简单来讲,有两种方法</p>
<!--more-->
<ol>
<li>通过源文件安装
这种方法比较繁琐,在上面链接中的<a href="http://zh-cn.broadcom.com/docs/linux_sta/README.txt">README</a>里面有安装过程的说明,如果是和我一样linux小白的话,一定要认真阅读。</li>
<li><p>通过yum安装
这种方法就比较人性咯,在上面的<a href="http://zh-cn.broadcom.com/docs/linux_sta/README.txt">README</a>里面也是有提及到的,这里也贴出来供欣赏</p>
<pre><code> su -c 'rpm -Uvh
http://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-stable.noarch.rpm
http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-stable.noarch.rpm'
su -
yum update //在这一步的时候总是提示一个错误,说xxx不是xxxx或者没有menifest文件,大概是这个,忘了具体是什么了。这会导致下一个命令找不到kmod-wl,多试几次yum update后,突然成功了。这东西太脆弱!
yum install kmod-wl
</code></pre></li>
</ol>
<p>再说说显卡驱动的安装,这个总体来说比较折腾了,我按照这个<a href="http://blog.csdn.net/uuleaf/article/details/7637341">博客</a>的方法安装成功了。</p>
<h2>Ubuntu</h2>
<p>严重的强迫症患者就是贱毛病多的,终于还是无法忍受那个不透明的终端了,虽然用的也不多,而且很怀念ubuntu那个经典的主题,最后还是决定换回Ubuntu(12.04)了。<br/>
对于初学者来讲,Ubuntu的确是很方便的,无线和显卡驱动起码不用太费心了。</p>
<h3>换主题</h3>
<p>Unity也许很优秀,但就是看不惯,个人觉得巨难用无比,那么第一步当然是切换回gnome classic主题</p>
<pre><code>sudo apt-get install gnome-panel
</code></pre>
<p>千万别运行那个</p>
<pre><code>sudo apt-get install gnome-shell
</code></pre>
<p>这个家伙会装上那个巨丑无比的gnome最新版的,真的好丑。
装上gnome-panel之后,就可以在登陆界面选择了,怎么选就不解释了。</p>
<h3>sogou输入法</h3>
<p>先删除ibus</p>
<pre><code>sudo apt-get remove ibus
</code></pre>
<p>卸载依赖</p>
<pre><code>sudo apt-get autoremove
</code></pre>
<p>安装输入法</p>
<pre><code>sudo add-apt-repository ppa:fcitx-team/nightly
sudo apt-get update
sudo apt-get install fcitx-sogoupinyin
</code></pre>
<p>剩下的找到fcitx配置,修改当前配置就好了,以您的智慧一看便懂了,友情提示,千万记得将换页修改为<code>,</code>和<code>.</code><br/>
全部搞定只有注销重新登录或者重启一次就可以用了。</p>
<h3>QQ</h3>
<p>以前一直用<a href="https://github.com/xiehuc/pidgin-lwqq">lwqq</a>,这个还是很不错的。这个<a href="https://github.com/xiehuc/pidgin-lwqq">官方链接</a>里面只给出了通过源码的方式安装,并不是很方便,而且通过这种方式,我编译就没有通过。采用这个<a href="https://github.com/xiehuc/pidgin-lwqq/wiki/Install-On-Linux">链接</a>给出的方法,安装成功</p>
<pre><code>$ sudo add-apt-repository ppa:lainme/pidgin-lwqq
$ sudo apt-get update
$ sudo apt-get install pidgin-lwqq
</code></pre>
<h3>ALT+TAB</h3>
<p>这是一个老问题了,切换到gnome桌面环境的Ubuntu12.04 Alt+Tap组合键失效了,这玩笑开大了,还得了了。
解决方法在<a href="https://bugs.launchpad.net/ubuntu/+source/compiz/+bug/971051">这里</a>,贴出来</p>
<pre><code>1. Install packages:
sudo apt-get install compiz-plugins compizconfig-settings-manager
2. Run "ccsm"
3. Scroll down to Window Management and enable (tick) "Application Switcher".
</code></pre>
<hr />
<p>就先写这么多了,以后再贴。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[献给GFW]]></title>
<link href="http://www.orcame.com/blog/2014/01/12/for-gfw/"/>
<updated>2014-01-12T16:23:00+08:00</updated>
<id>http://www.orcame.com/blog/2014/01/12/for-gfw</id>
<content type="html"><![CDATA[<p>——————/´ ¯/) <br/>
—————–/—-/ <br/>
—————-/—-/ <br/>
———–/´¯/’–’/´¯`·<em> <br/>
———-/’/–/—-/—–/¨¯\ <br/>
——–(‘(———- ¯~/’–’) <br/>
———\————-‘—–/ <br/>
———-‘'————</em>-·´ <br/>
————\———–( <br/>
————-\———–</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[通过Javascript上传文件到Azure存储服务器]]></title>
<link href="http://www.orcame.com/blog/2014/01/02/upload-azure-blob-by-javascript/"/>
<updated>2014-01-02T19:32:00+08:00</updated>
<id>http://www.orcame.com/blog/2014/01/02/upload-azure-blob-by-javascript</id>
<content type="html"><![CDATA[<p>Azure的存储服务目前开通了跨域访问<a href="http://en.wikipedia.org/wiki/Cross-origin_resource_sharing">CORS</a>请求功能,有了这个功能,我们就可以将被本地文件通过javascript上传到azure的存储服务器上了,而这个过程不需要任何服务器端代码就可以完成。你可以到这里看一下<a href="http://www.orcame.com/jquery-blobuploader/">演示效果</a>!下面来看看怎么实现这个功能。</p>
<!--more-->
<h2>准备工具</h2>
<ul>
<li>支持HTML5的浏览器一枚</li>
<li>文本编辑器一个</li>
<li>javascript打字员一名</li>
<li>测试上传用文件若干</li>
</ul>
<h2>准备条件</h2>
<h3>存储服务器</h3>
<p>经过一段时间的试用和测试,Windows Azure Storage的性能和稳定性都是非常高的,访问速度很快,这个我们可以用本次实验的结果给出证明。我选用了Azure中国(MoonCake)的存储服务,数据中心在上海。想要实现通过JS在浏览器端将文件提交到Azure Storage,需要满足以下两个条件。</p>
<ol>
<li>取得Azure Storage的访问权限
有关这个问题,我前一篇博客已经对SAS做了比较详细的介绍,<a href="http://www.orcame.com/blog/2013/12/29/windows-azure-sas-introduce/">传送门</a>。我们这里采用在Container级别上设置SAS的方式取得对Azure Storage的访问权限</li>
<li>将Azure Storage Account设置为允许跨域请求<br/>
Azure Storage已经开通了跨域请求功能,详细信息请移步<a href="http://blogs.msdn.com/b/windowsazurestorage/archive/2013/11/27/windows-azure-storage-release-introducing-cors-json-minute-metrics-and-more.aspx">这里</a>,默认是关闭的,要想使用这个功能,我们需要对存储账户做一些设置。不幸的是Azure Portal上找不到设置入口,你只能通过API来实现。截止目前(01/03/2014),MoonCake平台依然不能运行Azure SDK 2.2以上版本(如果你胆敢发布一个基于SDK2.2的Cloud Service,那么MoonCake很生气,后果很严重——不但你的Cloud Service发布失败,而且你的整个Subscription的Portal页面也全挂了),但亲测在本地运行Azure Storage SDK3.0是可以成功开启MoonCake上Storage的CORS功能的。</li>
</ol>
<p>附上开启CORS功能的API:</p>
<figure class='code'><figcaption><span>为Azure Storage Account开启CORS功能</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
</pre></td><td class='code'><pre><code class='c#'><span class='line'><span class="k">public</span> <span class="k">void</span> <span class="nf">OpenCors</span><span class="p">()</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'> <span class="n">CloudStorageAccount</span> <span class="n">account</span> <span class="p">=</span> <span class="n">CloudStorageAccount</span><span class="p">.</span><span class="n">Parse</span><span class="p">(</span><span class="n">connectionString</span><span class="p">);</span>
</span><span class='line'> <span class="n">CloudBlobClient</span> <span class="n">client</span> <span class="p">=</span> <span class="n">account</span><span class="p">.</span><span class="n">CreateCloudBlobClient</span><span class="p">();</span>
</span><span class='line'> <span class="n">ServiceProperties</span> <span class="n">propers</span> <span class="p">=</span> <span class="n">client</span><span class="p">.</span><span class="n">GetServiceProperties</span><span class="p">();</span>
</span><span class='line'> <span class="n">CorsRule</span> <span class="n">cr</span> <span class="p">=</span> <span class="k">new</span> <span class="n">CorsRule</span><span class="p">();</span>
</span><span class='line'> <span class="n">cr</span><span class="p">.</span><span class="n">AllowedMethods</span> <span class="p">=</span> <span class="n">CorsHttpMethods</span><span class="p">.</span><span class="n">Put</span> <span class="p">|</span> <span class="n">CorsHttpMethods</span><span class="p">.</span><span class="n">Options</span> <span class="p">|</span> <span class="n">CorsHttpMethods</span><span class="p">.</span><span class="n">Post</span> <span class="p">|</span> <span class="n">CorsHttpMethods</span><span class="p">.</span><span class="n">Delete</span> <span class="p">|</span> <span class="n">CorsHttpMethods</span><span class="p">.</span><span class="n">Get</span><span class="p">;</span>
</span><span class='line'> <span class="n">cr</span><span class="p">.</span><span class="n">AllowedOrigins</span><span class="p">.</span><span class="n">Add</span><span class="p">(</span><span class="s">"[your domain]"</span><span class="p">);</span><span class="c1">//http://www.orcame.com for example</span>
</span><span class='line'> <span class="n">cr</span><span class="p">.</span><span class="n">AllowedHeaders</span><span class="p">.</span><span class="n">Add</span><span class="p">(</span><span class="s">"*"</span><span class="p">);</span>
</span><span class='line'> <span class="n">cr</span><span class="p">.</span><span class="n">MaxAgeInSeconds</span> <span class="p">=</span> <span class="m">200</span><span class="p">;</span>
</span><span class='line'> <span class="n">propers</span><span class="p">.</span><span class="n">Cors</span> <span class="p">=</span> <span class="k">new</span> <span class="n">CorsProperties</span><span class="p">();</span>
</span><span class='line'> <span class="n">propers</span><span class="p">.</span><span class="n">Cors</span><span class="p">.</span><span class="n">CorsRules</span><span class="p">.</span><span class="n">Add</span><span class="p">(</span><span class="n">cr</span><span class="p">);</span>
</span><span class='line'> <span class="n">client</span><span class="p">.</span><span class="n">SetServiceProperties</span><span class="p">(</span><span class="n">propers</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<h3>浏览器</h3>
<p>用javascript上传文件我们必须能够取得对本地文件的读取操作,在HTML5之前这是不被允许的,
现代浏览器为我们提供了一个崭新的javascript API,FileReader,这使得我们可以异步的读取本地文件,甚至可以将文件拆分。有关FileReader的用法,我们在接下来的代码环节进行展开。</p>
<h2>功能列表</h2>
<p>本次实验我们要实现的功能如下</p>
<ol>
<li>文件上传</li>
<li>并发控制</li>
<li>断点续传</li>
</ol>
<h2>实验步骤</h2>
<h3>文件上传</h3>
<p>根据前面的分析,想要实现一个文件上传功能,需要用到FileReader对本地文件进行读取,然后通过ajax来发起上传请求到Azure Storage服务器</p>
<p>对于File,FileReader类,这里不做更详细的介绍,仅仅说明一下这里需要用到的方法和事件。</p>
<ul>
<li>File.slice(start,end)
有关slice方法的详细介绍请参考<a href="http://www.w3.org/TR/FileAPI/#slice-method-algo">这里</a>,简单来讲,就是这个方法可以根据传入的start和end将一个文件拆分成一个块(在js中叫blob,在azure中叫block,而在azure中js中的file叫blob,我勒个去,好绕),假设我们有一个<code><input type='file'/></code>控件,那么当我们选定了一个文件之后,是可以通过<code>files[0]</code>取得当前文件的实例的。</li>
<li>FileReader.readAsArrayBuffer(blob)
惯例,官方文档在<a href="http://www.w3.org/TR/FileAPI/#readAsArrayBuffer">这里</a>,这个方法可以将一个blob(azure中的block)读入到FileReader实例中</li>
<li>FileReader.onloadend(ev)
<a href="http://www.w3.org/TR/FileAPI/#event-handler-attributes-section">传送门</a>,简单来讲这是一个事件,当上面的readAsArrayBuffer执行结束后会触发这个事件。</li>
</ul>
<p>关于ajax请求如何发送,这里不赘述,请参考jquery<a href="http://api.jquery.com/jquery.ajax/">文档</a></p>
<p>在正式开始之前,我们得先明确几个概念</p>
<ul>
<li>File(JS):指代本地一个文件</li>
<li>Blob(JS):指代本地文件被拆分出的一块,相当于Azure中的Block</li>
<li>Blob(Azure):一个文件,可以由无数个Block组成</li>
<li>Block:无数个Block组成一个Blob</li>
</ul>
<p>为简单起见,本文以下内容,对于文件统称blob,块统称block</p>
<p>说了好多废话,现在开席,上菜了。</p>
<p>有了上面的介绍,一个内容上传的功能就很容易实现了,且看代码</p>
<figure class='code'><figcaption><span>上传block代码</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="kd">var</span> <span class="nx">sendBlock</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">block</span><span class="p">,</span> <span class="nx">beforeSend</span><span class="p">,</span> <span class="nx">progress</span><span class="p">,</span> <span class="nx">success</span><span class="p">,</span> <span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span>
</span><span class='line'> <span class="nx">url</span><span class="o">:</span> <span class="nx">block</span><span class="p">.</span><span class="nx">url</span><span class="p">,</span>
</span><span class='line'> <span class="nx">type</span><span class="o">:</span> <span class="s2">"PUT"</span><span class="p">,</span>
</span><span class='line'> <span class="nx">data</span><span class="o">:</span> <span class="nx">block</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span>
</span><span class='line'> <span class="nx">processData</span><span class="o">:</span> <span class="kc">false</span><span class="p">,</span>
</span><span class='line'> <span class="nx">xhr</span><span class="o">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">_xhr</span> <span class="o">=</span> <span class="nx">$</span><span class="p">.</span><span class="nx">ajaxSettings</span><span class="p">.</span><span class="nx">xhr</span><span class="p">();</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="nx">_xhr</span><span class="p">.</span><span class="nx">upload</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">_xhr</span><span class="p">.</span><span class="nx">upload</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="s1">'progress'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">ev</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="c1">//这里为了获取上传进度,我们添加了progress事件,在事件中可以做一些UI上的进度显示功能</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="nx">ev</span><span class="p">.</span><span class="nx">lengthComputable</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="nx">progress</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">progress</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="nx">block</span><span class="p">,</span><span class="nx">ev</span><span class="p">.</span><span class="nx">loaded</span><span class="p">,</span><span class="nx">ev</span><span class="p">.</span><span class="nx">total</span><span class="p">)</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">},</span> <span class="kc">false</span><span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="k">return</span> <span class="nx">_xhr</span><span class="p">;</span>
</span><span class='line'> <span class="p">},</span>
</span><span class='line'> <span class="nx">beforeSend</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">xhr</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">block</span><span class="p">.</span><span class="nx">status</span><span class="o">=</span><span class="s1">'uploading'</span><span class="p">;</span>
</span><span class='line'> <span class="nx">xhr</span><span class="p">.</span><span class="nx">setRequestHeader</span><span class="p">(</span><span class="s1">'x-ms-blob-type'</span><span class="p">,</span> <span class="s1">'BlockBlob'</span><span class="p">);</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="nx">beforeSend</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="c1">//在上传开始之前,你可以通过这个事件做一些小动作</span>
</span><span class='line'> <span class="nx">beforeSend</span><span class="p">(</span><span class="nx">xhr</span><span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">},</span>
</span><span class='line'> <span class="nx">success</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">data</span><span class="p">,</span> <span class="nx">sta</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">block</span><span class="p">.</span><span class="nx">status</span><span class="o">=</span><span class="s1">'success'</span><span class="p">;</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="nx">success</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="c1">//上传成功后,用这个方法通知UI</span>
</span><span class='line'> <span class="nx">success</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="nx">block</span><span class="p">,</span><span class="nx">data</span><span class="p">,</span> <span class="nx">status</span><span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">},</span>
</span><span class='line'> <span class="nx">error</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">xhr</span><span class="p">,</span> <span class="nx">desc</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">block</span><span class="p">.</span><span class="nx">status</span><span class="o">=</span><span class="s1">'error'</span><span class="p">;</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="c1">//同理,失败了用这个方法通知UI</span>
</span><span class='line'> <span class="nx">error</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="nx">block</span><span class="p">,</span> <span class="nx">xhr</span><span class="p">,</span> <span class="nx">desc</span><span class="p">,</span> <span class="nx">err</span><span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">});</span>
</span><span class='line'><span class="p">};</span>
</span></code></pre></td></tr></table></div></figure>
<p>上面就是一个最基本的block上传功能,如果要实现一个blob的上传,我们还需要做进一步的改进。首先就需要对blob进行拆分,因为azure的storage对block的大小有个限制,最大不能超过4M,所以我们的拆分上限就是4M。
有了上面的代码片段,实现一个blob的上传就很容易了,我们可以传入success方法,在前一个block上传成功了之后继续上传下一个block,直到所有block全部上传完毕。下面仅仅给出逻辑实现:</p>
<figure class='code'><figcaption><span>上传一个blob</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="kd">var</span> <span class="nx">_blob</span><span class="p">;</span>
</span><span class='line'><span class="kd">function</span> <span class="nx">success</span><span class="o">=</span><span class="p">(){</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">block</span> <span class="o">=</span><span class="k">this</span><span class="p">.</span><span class="nx">blob</span><span class="p">.</span><span class="nx">nextBlock</span><span class="p">();</span>
</span><span class='line'> <span class="k">if</span><span class="p">(</span><span class="nx">block</span><span class="p">){</span>
</span><span class='line'> <span class="c1">//在这里,我们做一个递归调用,一旦block上传完毕,就继续上传下一个block,直到所有block都完成为止。</span>
</span><span class='line'> <span class="nx">sendBlock</span><span class="p">(</span><span class="nx">block</span><span class="p">,</span><span class="kc">null</span><span class="p">,</span><span class="kc">null</span><span class="p">,</span><span class="nx">success</span><span class="p">,</span><span class="nx">error</span><span class="p">);</span>
</span><span class='line'> <span class="p">}</span><span class="k">else</span><span class="p">{</span>
</span><span class='line'> <span class="c1">//所有Block都上传完成了,这里需要做一个commit动作,就是通知azure storage,我刚刚上传的那些block是属于同一个blob的,请合并。</span>
</span><span class='line'> <span class="nx">commitBlob</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">blob</span><span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kd">function</span> <span class="nx">error</span><span class="p">(){</span>
</span><span class='line'> <span class="c1">//预留占位 </span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kd">function</span> <span class="nx">commitBlob</span><span class="p">(</span><span class="nx">blob</span><span class="p">,</span><span class="nx">success</span><span class="p">,</span><span class="nx">error</span><span class="p">){</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">uri</span> <span class="o">=</span> <span class="nx">blob</span><span class="p">.</span><span class="nx">url</span> <span class="o">+</span> <span class="s1">'&comp=blocklist'</span>
</span><span class='line'> <span class="p">,</span> <span class="nx">data</span> <span class="o">=</span> <span class="p">[]</span>
</span><span class='line'> <span class="p">,</span> <span class="nx">len</span> <span class="o">=</span> <span class="nx">blob</span><span class="p">.</span><span class="nx">blocks</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
</span><span class='line'> <span class="c1">//blob的commit需要提供一个blockid列表,这个列表中的所有项的长度必须一致,并且顺序不能错乱</span>
</span><span class='line'> <span class="nx">data</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="s1">'<?xml version="1.0" encoding="utf-8"?><BlockList>'</span><span class="p">);</span>
</span><span class='line'> <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">len</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">data</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="s1">'<Latest>'</span> <span class="o">+</span> <span class="nx">blob</span><span class="p">.</span><span class="nx">blocks</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">id</span> <span class="o">+</span> <span class="s1">'</Latest>'</span><span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="nx">data</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="s1">'</BlockList>'</span><span class="p">);</span>
</span><span class='line'> <span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span>
</span><span class='line'> <span class="nx">url</span><span class="o">:</span> <span class="nx">uri</span><span class="p">,</span>
</span><span class='line'> <span class="nx">type</span><span class="o">:</span> <span class="s2">"PUT"</span><span class="p">,</span>
</span><span class='line'> <span class="nx">data</span><span class="o">:</span> <span class="nx">data</span><span class="p">.</span><span class="nx">join</span><span class="p">(</span><span class="s1">''</span><span class="p">),</span>
</span><span class='line'> <span class="nx">beforeSend</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">xhr</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">xhr</span><span class="p">.</span><span class="nx">setRequestHeader</span><span class="p">(</span><span class="s1">'x-ms-blob-content-type'</span><span class="p">,</span> <span class="nx">blob</span><span class="p">.</span><span class="nx">type</span><span class="p">);</span>
</span><span class='line'> <span class="p">},</span>
</span><span class='line'> <span class="nx">success</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">data</span><span class="p">,</span> <span class="nx">sta</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="nx">success</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">success</span><span class="p">(</span><span class="nx">data</span><span class="p">,</span> <span class="nx">sta</span><span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">},</span>
</span><span class='line'> <span class="nx">error</span><span class="o">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">xhr</span><span class="p">,</span> <span class="nx">desc</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="k">if</span> <span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'> <span class="nx">error</span><span class="p">(</span><span class="nx">xhr</span><span class="p">,</span> <span class="nx">desc</span><span class="p">,</span> <span class="nx">err</span><span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">});</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kd">var</span> <span class="nx">_block</span><span class="o">=</span><span class="nx">_blob</span><span class="p">.</span><span class="nx">nextBlock</span><span class="p">();</span>
</span><span class='line'><span class="nx">sendBlock</span><span class="p">(</span><span class="nx">_block</span><span class="p">,</span><span class="kc">null</span><span class="p">,</span><span class="kc">null</span><span class="p">,</span><span class="nx">success</span><span class="p">,</span><span class="nx">error</span><span class="p">);</span><span class="c1">//这里开始上传</span>
</span></code></pre></td></tr></table></div></figure>
<p>通过上面这两段简单的代码,我们就可以实现一个文件的上传操作了。总结起来的步骤就是</p>
<ol>
<li>根据设定的blockSize从blob中取得下一个block</li>
<li>上传block</li>
<li>如果blob中还有block,回到1,否则到4</li>
<li>commit刚刚上传的blob</li>
</ol>
<h3>并发控制</h3>
<p>上面的步骤只是实现了最基本的上传功能,并且上传是单线程按序进行的,就是说一个文件同时只有一个block在上传,之后这个block上传成功了,下一个block才会开始上传。那么如果我想同时上传多个文件,并且同一个文件也可以多个block同时上传该怎么办呢?</p>
<p>因为在ajax的请求中,所有动作都是异步的,那么有很多事情我们需要在回调函数中才能处理,这也是为什么上面的代码对外开放了success和error两个事件回调的主要原因。</p>
<p>对于单个文件的上传,要支持多请求并发是比较容易实现的,可以设想一个请求计数器,初始值为我们预设的最大请求数量。设定一个循环,每发起一个请求,计数器自减1,每个请求成功了之后,同样是按照上面的规则,如果还有block,就开启一个新的请求,需要注意的是,只有所有的block全部上传成功了,我们才能进行blob的commit操作,需要对success方法做一个小改动。</p>
<figure class='code'><figcaption><span>并发上传blob</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="kd">var</span> <span class="nx">maxThread</span><span class="o">=</span><span class="mi">20</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'><span class="kd">function</span> <span class="nx">blobUploadFinished</span><span class="p">(</span><span class="nx">blob</span><span class="p">){</span>
</span><span class='line'> <span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">idx</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="nx">idx</span><span class="o"><</span><span class="nx">blob</span><span class="p">.</span><span class="nx">blocks</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="nx">idx</span><span class="o">++</span><span class="p">){</span>
</span><span class='line'> <span class="k">if</span><span class="p">(</span><span class="nx">blob</span><span class="p">.</span><span class="nx">blocks</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">status</span><span class="o">!=</span><span class="s1">'success'</span><span class="p">){</span>
</span><span class='line'> <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kd">function</span> <span class="nx">success</span><span class="o">=</span><span class="p">(){</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">blob</span><span class="o">=</span><span class="k">this</span><span class="p">.</span><span class="nx">blob</span><span class="p">;</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">block</span> <span class="o">=</span><span class="k">this</span><span class="p">.</span><span class="nx">blob</span><span class="p">.</span><span class="nx">nextBlock</span><span class="p">();</span>
</span><span class='line'> <span class="k">if</span><span class="p">(</span><span class="nx">block</span><span class="p">){</span>
</span><span class='line'> <span class="c1">//这里开启一个新的请求上传获取到的下一个block</span>
</span><span class='line'> <span class="nx">sendBlock</span><span class="p">(</span><span class="nx">block</span><span class="p">,</span><span class="kc">null</span><span class="p">,</span><span class="kc">null</span><span class="p">,</span><span class="nx">success</span><span class="p">,</span><span class="nx">error</span><span class="p">);</span>
</span><span class='line'> <span class="p">}</span><span class="k">else</span><span class="p">{</span>
</span><span class='line'> <span class="k">if</span><span class="p">(</span><span class="nx">blobUploadFinished</span><span class="p">(</span><span class="nx">blob</span><span class="p">)){</span><span class="c1">//所有block都上传成功了,再commit</span>
</span><span class='line'> <span class="nx">commitBlob</span><span class="p">(</span><span class="nx">blob</span><span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="k">while</span><span class="p">(</span><span class="nx">maxThread</span><span class="o">==-</span><span class="mi">1</span> <span class="o">||</span> <span class="nx">maxThread</span><span class="o">></span><span class="mi">0</span><span class="p">){</span>
</span><span class='line'> <span class="c1">//maxThread = -1意味着无限定,所有block可以同时上传,强烈不建议这样做,实测400M+的文件导致chrome崩溃(电脑配置也比较烂)</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">block</span> <span class="o">=</span><span class="nx">_blob</span><span class="p">.</span><span class="nx">nextBlock</span><span class="p">();</span>
</span><span class='line'> <span class="k">if</span><span class="p">(</span><span class="nx">block</span><span class="p">){</span>
</span><span class='line'> <span class="nx">sendBlock</span><span class="p">(</span><span class="nx">block</span><span class="p">,</span><span class="kc">null</span><span class="p">,</span><span class="kc">null</span><span class="p">,</span><span class="nx">success</span><span class="p">,</span><span class="nx">error</span><span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="k">if</span><span class="p">(</span><span class="nx">maxThread</span><span class="o">></span><span class="mi">0</span><span class="p">){</span>
</span><span class='line'> <span class="nx">maxThread</span><span class="o">--</span><span class="p">;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>一个blob的多请求并发上传功能实现了,那么如果我想对多个blob进行处理该怎么办呢?其实原理也是一样的,还是有一个最大请求限定,只不过我们需要事先将所有的blob放入一个数组,上面的while循环就多了一步验证所有blob是否全部没有待上传block的步骤。</p>
<figure class='code'><figcaption><span>并发上传多个blob</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="kd">var</span> <span class="nx">blobs</span><span class="o">=</span><span class="p">[];</span>
</span><span class='line'><span class="c1">//push all your blob in blobs here.</span>
</span><span class='line'><span class="kd">function</span> <span class="nx">nextBlock</span><span class="p">(){</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">len</span> <span class="o">=</span> <span class="nx">blobs</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
</span><span class='line'> <span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">idx</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="nx">idx</span><span class="o"><</span><span class="nx">len</span><span class="p">;</span><span class="nx">idx</span><span class="o">++</span><span class="p">){</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">block</span><span class="o">=</span><span class="nx">blobs</span><span class="p">[</span><span class="nx">idx</span><span class="p">].</span><span class="nx">nextBlock</span><span class="p">();</span>
</span><span class='line'> <span class="k">if</span><span class="p">(</span><span class="nx">block</span><span class="p">){</span>
</span><span class='line'> <span class="k">return</span> <span class="nx">block</span><span class="p">;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="k">while</span><span class="p">(</span><span class="nx">maxThread</span><span class="o">==-</span><span class="mi">1</span> <span class="o">||</span> <span class="nx">maxThread</span><span class="o">></span><span class="mi">0</span><span class="p">){</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">block</span> <span class="o">=</span><span class="nx">nextBlock</span><span class="p">();</span>
</span><span class='line'> <span class="k">if</span><span class="p">(</span><span class="nx">block</span><span class="p">){</span>
</span><span class='line'> <span class="nx">sendBlock</span><span class="p">(</span><span class="nx">block</span><span class="p">,</span><span class="kc">null</span><span class="p">,</span><span class="kc">null</span><span class="p">,</span><span class="nx">success</span><span class="p">,</span><span class="nx">error</span><span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="k">if</span><span class="p">(</span><span class="nx">maxThread</span><span class="o">></span><span class="mi">0</span><span class="p">){</span>
</span><span class='line'> <span class="nx">maxThread</span><span class="o">--</span><span class="p">;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<h3>断点续传</h3>
<p>细心的会很快发现,我们上面的代码都是围绕着success回调方法做一些简单的改动就可以实现单线程或者并发的上传操作,那么断点续传该怎样处理呢?bingo,答对了,error回调方法可以很好的帮我们解决这个问题。
断点续传的简单思路就是将那些上传失败的block重新上传,直到所有block全部上传成功了,才结束提交blob,结束整个上传过程。</p>
<figure class='code'><figcaption><span>一个简单error回调的实现</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="kd">function</span> <span class="nx">error</span><span class="p">(){</span>
</span><span class='line'><span class="nx">sendBlock</span><span class="p">(</span><span class="k">this</span><span class="p">,</span><span class="kc">null</span><span class="p">,</span><span class="kc">null</span><span class="p">,</span><span class="nx">success</span><span class="p">,</span><span class="nx">error</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>这个error回调真是简单到极致了,总觉得哪里有问题,不是么?当我有多个文件需要上传,而因为某种原因,这个block总是失败怎么办?那么他走时占用一个请求,循环啊循环,永无止境。我们做个小改动试试看。</p>
<figure class='code'><figcaption><span>改进的error回调</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="kd">function</span> <span class="nx">error</span><span class="p">(){</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">blob</span><span class="p">.</span><span class="nx">addErrorBlock</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">block</span><span class="o">=</span><span class="nx">nextBlock</span><span class="p">();</span>
</span><span class='line'> <span class="nx">sendBlock</span><span class="p">(</span><span class="nx">block</span><span class="p">,</span><span class="kc">null</span><span class="p">,</span><span class="kc">null</span><span class="p">,</span><span class="nx">success</span><span class="p">,</span><span class="nx">error</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>在这段代码中,我们将失败的block加入到blob的失败列表中,接着从blob列表中获取取下一个可用的block进行上传。
这样我们就实现了简单的断点续传功能。</p>
<h3>补充说明</h3>
<p>下面我们补充一下上面用到的但还没有见到长什么样子的代码。</p>
<figure class='code'><figcaption><span>久违的blob和block</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
</pre></td><td class='code'><pre><code class='js'><span class='line'><span class="kd">var</span> <span class="nx">blob</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">file</span><span class="p">,</span><span class="nx">containerUrl</span><span class="p">,</span><span class="nx">blockSize</span><span class="p">){</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">file</span><span class="o">=</span><span class="nx">file</span><span class="p">;</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">qidx</span><span class="o">=</span><span class="nx">containerUrl</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="s2">"?"</span><span class="p">);</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">blobUrl</span><span class="o">=</span><span class="nx">containerUrl</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">qidx</span><span class="p">)</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="o">+</span> <span class="nx">file</span><span class="p">.</span><span class="nx">name</span><span class="p">;</span><span class="c1">//记录blob的链接</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">url</span><span class="o">=</span><span class="k">this</span><span class="p">.</span><span class="nx">blobUrl</span> <span class="o">+</span> <span class="nx">containerUrl</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="nx">qidx</span><span class="p">);</span><span class="c1">//记录blob包括sas的链接</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">blockSize</span><span class="o">=</span><span class="nx">blockSize</span><span class="p">;</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">errorBlocks</span><span class="o">=</span><span class="p">[];</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">blocks</span><span class="o">=</span><span class="p">[];</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="nx">blob</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">nextBlock</span><span class="o">=</span><span class="kd">function</span><span class="p">(){</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">file</span><span class="o">=</span><span class="k">this</span><span class="p">.</span><span class="nx">file</span><span class="p">;</span>
</span><span class='line'> <span class="k">if</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">pointer</span><span class="o"><</span><span class="nx">file</span><span class="p">.</span><span class="nx">size</span><span class="p">){</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">_block</span> <span class="o">=</span> <span class="nx">file</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">pointer</span><span class="p">,</span><span class="k">this</span><span class="p">.</span><span class="nx">pointer</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">fileSize</span><span class="p">);</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">pointer</span><span class="o">+=</span><span class="nx">_block</span><span class="p">.</span><span class="nx">size</span><span class="p">;</span>
</span><span class='line'> <span class="k">return</span> <span class="k">new</span> <span class="nx">block</span><span class="p">(</span><span class="k">this</span><span class="p">,</span><span class="nx">_block</span><span class="p">);</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">errorBlocks</span><span class="p">.</span><span class="nx">shift</span><span class="p">();</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="nx">blob</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">addErrorBlock</span><span class="p">(</span><span class="nx">block</span><span class="p">){</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">errorBlocks</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">block</span><span class="p">);</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kd">function</span> <span class="nx">padstr</span><span class="p">(</span><span class="nx">num</span><span class="p">){</span>
</span><span class='line'> <span class="kd">var</span> <span class="nx">str</span><span class="o">=</span><span class="s1">''</span><span class="o">+</span><span class="nx">num</span><span class="p">;</span>
</span><span class='line'> <span class="k">while</span><span class="p">(</span><span class="kc">true</span><span class="p">){</span>
</span><span class='line'> <span class="k">if</span><span class="p">(</span><span class="nx">str</span><span class="p">.</span><span class="nx">length</span><span class="o"><</span><span class="mi">6</span><span class="p">){</span>
</span><span class='line'> <span class="nx">str</span><span class="o">+=</span><span class="s1">'0'</span><span class="p">;</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="k">return</span> <span class="nx">num</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="kd">var</span> <span class="nx">block</span><span class="o">=</span><span class="kd">function</span><span class="p">(</span><span class="nx">blob</span><span class="p">,</span><span class="nx">fileSlice</span><span class="p">){</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">blob</span><span class="o">=</span><span class="nx">blob</span><span class="p">;</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">data</span><span class="o">=</span><span class="nx">fileSlice</span><span class="p">;</span>
</span><span class='line'> <span class="nx">blob</span><span class="p">.</span><span class="nx">blocks</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">id</span><span class="o">=</span><span class="nx">btoa</span><span class="p">(</span><span class="s2">"block-"</span> <span class="o">+</span> <span class="nx">pad</span><span class="p">(</span><span class="nx">blob</span><span class="p">.</span><span class="nx">blocks</span><span class="p">.</span><span class="nx">length</span><span class="p">)).</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/=/g</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">);</span>
</span><span class='line'> <span class="k">this</span><span class="p">.</span><span class="nx">url</span><span class="o">=</span><span class="nx">blob</span><span class="p">.</span><span class="nx">url</span><span class="o">+</span><span class="s1">'&comp=block&blockid='</span> <span class="o">+</span> <span class="nx">block</span><span class="p">.</span><span class="nx">id</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p><strong>注意</strong>文章中的代码片段只是提供一个思路,如果您需要完整的代码,请参考我github上的一个<a href="https://github.com/orcame/jquery-blobuploader">jquery插件</a>。</p>
<h2>测试</h2>
<p>我写了一个简单的测试页面,截图如下:
<img src="http://www.orcame.com/images/image-post/blobuploader-0.png"></p>
<p>添加几个文件,做个简单的测试后,得到的数据如下</p>
<table>
<thead>
<tr>
<th>文件大小</th>
<th>Block Size</th>
<th>Max Thread</th>
<th>最大速度</th>
<th>最小速度</th>
<th>平均速度</th>
</tr>
</thead>
<tbody>
<tr>
<td>364M</td>
<td>2M</td>
<td>20</td>
<td>170M/S</td>
<td>54K/S</td>
<td>9.8M/S</td>
</tr>
<tr>
<td>693M</td>
<td>2M</td>
<td>20</td>
<td>290M/S</td>
<td>126K/S</td>
<td>12M/S</td>
</tr>
<tr>
<td>693M</td>
<td>4M</td>
<td>10</td>
<td>550M/S</td>
<td>59K/S</td>
<td>11.8M/S</td>
</tr>
<tr>
<td>1.35M</td>
<td>4M</td>
<td>10</td>
<td>4M/S</td>
<td>110K/S</td>
<td>680K/S</td>
</tr>
</tbody>
</table>
<p>统计结果中最大速度波动比较大,这个基本都是瞬时速度,不具备什么参考价值。也有可能我统计的方式不对!</p>
<h2>后记</h2>
<p>这之后有做过一些测试,这个和当前的网络情况有很大关系,每隔一段时间,测试的结果波动都非常大。后来在Azure上面建了一个虚拟机,通过走数据中心内部的网络进行测试,对于135M左右的文件,基本稳定在5s以内可以上传完毕,这个速度还是非常可观的。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[使用markdown问题汇总]]></title>
<link href="http://www.orcame.com/blog/2013/12/30/markdown-issue-list/"/>
<updated>2013-12-30T21:09:00+08:00</updated>
<id>http://www.orcame.com/blog/2013/12/30/markdown-issue-list</id>
<content type="html"><![CDATA[<p>这个博客(基于<a href="https://github.com/imathis/octopress">Octopress</a>)搭建已经有一段时间了,一直没怎么写,一是因为自己很懒,二也是因为一直不知道写什么,最近强迫自己写一些东西,因为有些内容还是值得记录下来的,权当做备忘录来使用。</p>
<p>这几天用<a href="http://en.wikipedia.org/wiki/Markdown">markdown</a>的过程中碰到了一些问题的,既然我能遇到这些问题,我相信也有其他人会遇到相似的问题,这里做个简单的记录,这篇博客也会在后续的使用当中不断更新。</p>
<!--more-->
<h3>列表为何无法正确显示</h3>
<p>第一个问题就是列表始终无法正确显示出来,譬如,我书写的是</p>
<pre><code>1. item1
2. item2
3. item3
</code></pre>
<p>最后generate出来的结果却是</p>
<pre><code>1. item12. item23. item3
</code></pre>
<p>无论我在每个点(.)后面预留多少个空格或者制表符,都无法得到想要的结果。无序列表也存在同样的问题。
解决方法是需要在每个列表块之前添加一个空白行,就像这样。</p>
<pre><code><!--这里放置一个空行-->
1. item1
2. item2
3. item3
</code></pre>
<h3>相邻两个列表块被合并了</h3>
<p>问题总是一个接着一个的,当我需要书写两个相邻的列表块的时候,出来的结果总是被合并成一个,即便一个是有序列表,一个是无序列表。
例如,我这样写</p>
<pre><code>1. item1 on list1
2. item2 on list1
3. item3 on list1
+ item1 on list2
+ item2 on list2
+ item2 on list2
</code></pre>
<p>出来的结果是这样的</p>
<ol>
<li>item1 on list1</li>
<li>item2 on list1</li>
<li><p>item3 on list1</p></li>
<li><p>item1 on list2</p></li>
<li>item2 on list2</li>
<li>item2 on list2</li>
</ol>
<p>这是一个很讨厌的问题,正要google的时候,突然,脑门上划过一道闪电,如果为两个列表块之间添加一个注释会怎么样?</p>
<pre><code>1. item1 on list1
2. item2 on list1
3. item3 on list1
<!--大哥,我想要两个列表块-->
+ item1 on list2
+ item2 on list2
+ item2 on list2
</code></pre>
<p>结果是,我真的得到了两个列表块.(^o^)/~</p>
<ol>
<li>item1 on list1</li>
<li>item2 on list1</li>
<li>item3 on list1</li>
</ol>
<!--大哥,我想要两个列表块-->
<ul>
<li>item1 on list2</li>
<li>item2 on list2</li>
<li>item2 on list2</li>
</ul>
<h3>如何在列表中显示代码块</h3>
<p>如果想把代码块嵌入列表中,那么你需要在代码块前面加一个空行,这个代码块前面的缩进至少为8个空格或者两个制表符,就像这样</p>
<pre><code>+ item 1
<!--这里有个空行-->
<!--这里两个制表符-->code block under item1
+ item 2
<!--这里有个空行-->
<!--或者8个空格-->code block under item2
</code></pre>
<p>显示的结果就是这样的</p>
<ul>
<li><p>item 1</p>
<pre><code> code block under item1
</code></pre></li>
<li><p>item 2</p>
<pre><code> code block under item2
</code></pre></li>
</ul>
<p>如果你想要将</p>
<pre><code>``` langname description
```
</code></pre>
<p>这种形式书写的代码块嵌入列表项中,我没有找到方法,我的判断是不可以,至少目前是这样。</p>
<h3>如何显示table</h3>
<p>目前为止,我还没有遇到需要写用table表达的内容的情况,这里纯粹好奇。
table是这样写的</p>
<pre><code>header1|header2|header3
---|---|---|
cell11|cell12|cell13
cell21|cell22|cell23
</code></pre>
<p>出来的结果是</p>
<table>
<thead>
<tr>
<th>header1</th>
<th>header2</th>
<th>header3</th>
</tr>
</thead>
<tbody>
<tr>
<td>cell11</td>
<td>cell12</td>
<td>cell13</td>
</tr>
<tr>
<td>cell21</td>
<td>cell22</td>
<td>cell23</td>
</tr>
</tbody>
</table>
<p>这里需要注意,这个<code>table</code>的<code>html</code>就是由纯粹的<code><table></code>,<code><thead></code>,<code><tbody></code>,<code><tr></code>,<code><td></code>等组成的,是没有诸如<code>class</code>等任何属性的,所以你看到的会是这个样子,那么如何为<code>table</code>添加<code>class</code>属性呢?我不知道,网上也有很多人再问这个问题了,现在比较通用的答案呢,都是为全局的<code>table</code>设置一个样式,譬如,加一个这样的样式表</p>
<figure class='code'><figcaption><span>table style</span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='css'><span class='line'><span class="nc">.entry-content</span> <span class="nt">table</span><span class="p">{</span>
</span><span class='line'> <span class="k">width</span><span class="o">:</span><span class="m">100</span><span class="o">%</span><span class="p">;</span>
</span><span class='line'> <span class="k">border</span><span class="o">:</span><span class="m">1px</span> <span class="k">solid</span> <span class="m">#333</span><span class="p">;</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="nc">.entry-content</span> <span class="nt">table</span> <span class="nt">thead</span><span class="p">{</span>
</span><span class='line'> <span class="c">/*thead style here*/</span>
</span><span class='line'><span class="p">}</span>
</span><span class='line'><span class="c">/*other style, tbody, tr, td and so on*/</span>
</span></code></pre></td></tr></table></div></figure>
<p>这个解决方案虽然比较ugly,但的确是可以解决这个问题的,我因为偷懒,没有加这个样式。也许将来有一天我突然勤快一下,你会看到这个table变样了。
另外,如果你想让一个单元格占据多行或者多列,(设置<code>colspan</code>或者<code>rowspan</code>),那么别想了,没有这个功能,或者你可以直接写html嵌入markdown文件。</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Windows Azure Shared Access Signature简介]]></title>
<link href="http://www.orcame.com/blog/2013/12/29/windows-azure-sas-introduce/"/>
<updated>2013-12-29T22:26:00+08:00</updated>
<id>http://www.orcame.com/blog/2013/12/29/windows-azure-sas-introduce</id>
<content type="html"><![CDATA[<h2>What</h2>
<p>Shared Access Signature(SAS),共享访问签名,是用于提供对Windows Azure Storage中的Container,Blob,Table以及Queue在特定时间范围内进行有限权限访问的URL。</p>
<!--more-->
<h2>Why</h2>
<p>通常情况下,对Azure Storage的访问是通过账户名和密钥来实现的,这样的认证方式赋予了使用者包括增删改在内的最大的访问权限,而实际应用当中,有许多场景是希望能够限定用户的权限的,比方常见的只读权限,并且也不希望将密钥泄露给用户,这样存在很大的安全隐患。使用SAS可以很好的解决这个问题。</p>
<h2>How</h2>
<h3>功能介绍</h3>
<p>SAS提供的功能包括</p>
<h5>For Blob</h5>
<ul>
<li>读写Blob及其属性和元数据</li>
<li>删除、租赁和创建 Blob 快照</li>
<li>读取Container的Blob列表</li>
</ul>
<h5>For Table</h5>
<ul>
<li>增、删、改、查(version>=’2012-02-12’可用)</li>
</ul>
<h5>For Queue</h5>
<ul>
<li>增删改队列消息(version>=’2012-02-12’可用)</li>
<li>读取队列元数据,消息计数(version>=’2012-02-12’可用)</li>
</ul>