-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
497 lines (298 loc) · 201 KB
/
atom.xml
File metadata and controls
497 lines (298 loc) · 201 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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>sevth的小破站</title>
<subtitle>一个野生coder</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="https://sevth.com/"/>
<updated>2020-07-24T14:10:52.427Z</updated>
<id>https://sevth.com/</id>
<author>
<name>sevth</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>vue使用动态路由,Eslint报错解决</title>
<link href="https://sevth.com/study/vue/vue%E4%BD%BF%E7%94%A8%E5%8A%A8%E6%80%81%E8%B7%AF%E7%94%B1,Eslint%E6%8A%A5%E9%94%99%E8%A7%A3%E5%86%B3.html"/>
<id>https://sevth.com/study/vue/vue%E4%BD%BF%E7%94%A8%E5%8A%A8%E6%80%81%E8%B7%AF%E7%94%B1,Eslint%E6%8A%A5%E9%94%99%E8%A7%A3%E5%86%B3.html</id>
<published>2020-07-24T13:59:04.000Z</published>
<updated>2020-07-24T14:10:52.427Z</updated>
<content type="html"><![CDATA[<blockquote><p>发现问题也只是工作的时候发现的,算不上什么大问题,最简单解决办法就是直接关闭 <code>Eslint</code>了,然后百度网上查了一下,发现找到相关解决办法,就记录一下。</p></blockquote><a id="more"></a><p>随便一提,做项目的时候,用了动态路由,之前用的 <code>laravel-mix</code> 打包,傻瓜化配置,后来因为一些别的问题,自定义某些配置一直有问题,就转向了官方的怀抱,用<code>vue-cli</code>重新配置项目,就启用了<code>Eslint</code>这个折磨人的东西。</p><p>发现问题是IDE直接报错提示的:</p><div class="highlight-container"><figure class=" highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">route.component = <span class="function"><span class="params">()</span> =></span> <span class="keyword">import</span>((<span class="string">`@/<span class="subst">${url}</span>`</span>))</span><br></pre></td></tr></table></figure></div><p>其实就是后台返回路由,前端再动态注册,解决办法就是换个写法.</p><div class="highlight-container"><figure class=" highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">route.component = <span class="function"><span class="params">resolve</span> =></span> <span class="built_in">require</span>([<span class="string">`@/<span class="subst">${url}</span>`</span>], resolve)</span><br></pre></td></tr></table></figure></div><h3 id="参考"><a href="#参考" class="headerlink" title="参考"></a>参考</h3><ul><li><a href="/go/?p">链接</a></li></ul>]]></content>
<summary type="html">
<blockquote>
<p>发现问题也只是工作的时候发现的,算不上什么大问题,最简单解决办法就是直接关闭 <code>Eslint</code>了,然后百度网上查了一下,发现找到相关解决办法,就记录一下。</p>
</blockquote>
</summary>
<category term="study" scheme="https://sevth.com/categories/study/"/>
<category term="vue" scheme="https://sevth.com/categories/study/vue/"/>
<category term="vue" scheme="https://sevth.com/tags/vue/"/>
<category term="router" scheme="https://sevth.com/tags/router/"/>
<category term="eslint" scheme="https://sevth.com/tags/eslint/"/>
</entry>
<entry>
<title>基于go语言编写的简单api爬虫</title>
<link href="https://sevth.com/study/golang/%E5%9F%BA%E4%BA%8Ego%E8%AF%AD%E8%A8%80%E7%BC%96%E5%86%99%E7%9A%84%E7%AE%80%E5%8D%95api%E7%88%AC%E8%99%AB.html"/>
<id>https://sevth.com/study/golang/%E5%9F%BA%E4%BA%8Ego%E8%AF%AD%E8%A8%80%E7%BC%96%E5%86%99%E7%9A%84%E7%AE%80%E5%8D%95api%E7%88%AC%E8%99%AB.html</id>
<published>2020-05-21T17:32:43.000Z</published>
<updated>2020-05-21T19:39:51.085Z</updated>
<content type="html"><![CDATA[<blockquote><p>起因是朋友月底要离职了,然后待的公司在系统里还有一些资料,想下载下来。手动一条一条下载太麻烦了,所以就找我帮忙看能不能用更科学的方法下载这些资料。</p><p>其实说是爬虫,不如说是一个自动采集下载的工具,其中,并没有实现分析网页源数据的功能,只是单纯的下载“公开”的数据。</p></blockquote><a id="more"></a><h2 id="接口分析"><a href="#接口分析" class="headerlink" title="接口分析"></a>接口分析</h2><p>首先来到登录界面,<code>https://example.com/auth/login</code>,<kbd>F12<kbd>打开<code>Chrome</code> 控制台分析。</p><p><img src="https://img.sevth.com/picture/2020/05/22/aCNoMpEWPKkfFZlH.png" alt="image-20200522021914274"></p><p>后台返回的数据是<code>json</code>,那么说明网站架构差不多是前后端分离的。然后发现了网页内嵌的一些<code>js</code>文件:</p><ul><li>Manifest.js</li><li>Vendor.js</li><li>Common.js</li></ul><p><img src="https://img.sevth.com/picture/2020/05/22/EhfOhnJVisAWRhYr.png" alt="image-20200522022335498"></p><p>这个<a href="/go/?m">熟悉</a>的感觉,后台应该是<code>laravel</code>, 那么前端很大可能就是<code>Vue</code>了(是啥也不重要)。</p><h3 id="用户授权方式"><a href="#用户授权方式" class="headerlink" title="用户授权方式"></a>用户授权方式</h3><p><code>laravel</code> 有很多种用户的认证方式,比如基于<code>Oauth2</code>的<a href="/go/?n"><code>Passport</code></a>,基于<code>Api</code>的<a href="/go/?o"><code>Sanctum</code></a>,这里直接用<code>Postman</code>请求登录 Api,获取到了<code>token</code>,看起来应该就是使用的<code>jwt-auth</code>插件了,使用基于<code>jwt</code>的<code>token</code>认证。</p><h3 id="一些API"><a href="#一些API" class="headerlink" title="一些API"></a>一些API</h3><p>登录后进入首页,直接从控制台查看网络请求,分析其中的接口,发现如下:</p><ul><li><a href="https://example.com/api/visible_list?page=1&per_page=10&showcenter=1">https://example.com/api/visible_list?page=1&per_page=10&showcenter=1</a> (控制台展示文件列表)</li><li><a href="https://example.com/api/listdir?page=1&per_page=10&showcenter=1&dirid=5481">https://example.com/api/listdir?page=1&per_page=10&showcenter=1&dirid=5481</a> (文件夹id查询内容)</li><li><a href="https://example.com/api/preview?id=5892">https://example.com/api/preview?id=5892</a> (根据文件id获取下载链接)</li></ul><h2 id="框架"><a href="#框架" class="headerlink" title="框架"></a>框架</h2><p>编写这么一个类似的应用,最重要的应该就是框架了,其中,框架应该有的东西有:</p><ol><li>队列</li><li>内容分析</li><li>其他等</li></ol><p>这个应该根据实际的需求添加,比如经典的爬虫,可以使用<code>python</code>的<code>scrapy</code>编写。它的功能很全面。</p><p>这里用<code>go</code>来写的原因只是因为对<code>python</code>不太感冒,然后这个简单的东西用<code>scrapy</code>不合(hui)适(yong)。</p><h3 id="数据结构"><a href="#数据结构" class="headerlink" title="数据结构"></a>数据结构</h3><p>看看请求返回的内容结构:</p><div class="highlight-container"><figure class=" highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="attr">"stat"</span>: <span class="string">"succ"</span>,</span><br><span class="line"> <span class="attr">"data"</span>: {</span><br><span class="line"> <span class="attr">"current_page"</span>: <span class="number">1</span>,</span><br><span class="line"> <span class="attr">"data"</span>: [</span><br><span class="line"> {</span><br><span class="line"> <span class="attr">"id"</span>: <span class="number">1032</span>,</span><br><span class="line"> <span class="attr">"size"</span>: <span class="string">"0"</span>,</span><br><span class="line"> <span class="attr">"updated_at"</span>: <span class="string">"2019-09-19 11:15:46"</span>,</span><br><span class="line"> <span class="attr">"name"</span>: <span class="string">"通用文档"</span>,</span><br><span class="line"> <span class="attr">"ftype"</span>: <span class="string">"dir"</span>,</span><br><span class="line"> <span class="attr">"osspath"</span>: <span class="string">""</span></span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="comment">// ...</span></span><br><span class="line"> }</span><br><span class="line"> ],</span><br><span class="line"> <span class="attr">"first_page_url"</span>: <span class="string">"https://example.com/api/visible_list?page=1"</span>,</span><br><span class="line"> <span class="attr">"from"</span>: <span class="number">1</span>,</span><br><span class="line"> <span class="attr">"last_page"</span>: <span class="number">1</span>,</span><br><span class="line"> <span class="attr">"last_page_url"</span>: <span class="string">"https://example.com/api/visible_list?page=1"</span>,</span><br><span class="line"> <span class="attr">"next_page_url"</span>: <span class="literal">null</span>,</span><br><span class="line"> <span class="attr">"path"</span>: <span class="string">"https://example.com/api/visible_list"</span>,</span><br><span class="line"> <span class="attr">"per_page"</span>: <span class="string">"10"</span>,</span><br><span class="line"> <span class="attr">"prev_page_url"</span>: <span class="literal">null</span>,</span><br><span class="line"> <span class="attr">"to"</span>: <span class="number">10</span>,</span><br><span class="line"> <span class="attr">"total"</span>: <span class="number">10</span></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>大致结构都是一样的,都是使用的<code>laravel</code>的分页功能,所以我们可以简化所有的文件夹或者文件为一个<code>field</code>,它的结构是这样的。</p><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Field <span class="keyword">struct</span> {</span><br><span class="line">Id <span class="keyword">int</span> <span class="string">`json:"id"`</span></span><br><span class="line">Name <span class="keyword">string</span> <span class="string">`json:"name"`</span></span><br><span class="line">Type <span class="keyword">string</span> <span class="string">`json:"ftype"`</span></span><br><span class="line">ParentId <span class="keyword">string</span> <span class="string">`json:"parent_id"`</span></span><br><span class="line">Size <span class="keyword">string</span> <span class="string">`json:"size"`</span></span><br><span class="line">OssPath <span class="keyword">string</span> <span class="string">`json:"osspath"`</span></span><br><span class="line">Path <span class="keyword">string</span> <span class="string">`json:"path"`</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>顶级的文件夹是没有<code>ParentId</code>属性的,这里使用<code>json</code>反序列化,没有的数据会自动填充为零值。</p><h3 id="队列"><a href="#队列" class="headerlink" title="队列"></a>队列</h3><p>既然所有的文件夹或者文件都是一个类似的<code>field</code>,那么我们可以设计一个队列,将首页获得的<code>field</code>存入队列,然后根据<code>field</code>类型进行对应操作,类型为文件夹的,通过<code>文件夹Api</code>取得这个文件夹下面的<code>field</code>并添加到队列的尾部,如果类型为文件,那么下载这个文件。</p><h4 id="队列的实现方法"><a href="#队列的实现方法" class="headerlink" title="队列的实现方法"></a>队列的实现方法</h4><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 队列</span></span><br><span class="line"><span class="keyword">type</span> Queue <span class="keyword">struct</span> {</span><br><span class="line">items []Field</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *Queue)</span> <span class="title">New</span><span class="params">()</span> *<span class="title">Queue</span></span> {</span><br><span class="line">s.items = []Field{}</span><br><span class="line"><span class="keyword">return</span> s</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *Queue)</span> <span class="title">Put</span><span class="params">(t Field)</span></span> {</span><br><span class="line">s.items = <span class="built_in">append</span>(s.items, t)<span class="comment">//插入数据到队列尾部</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *Queue)</span> <span class="title">Get</span><span class="params">()</span> *<span class="title">Field</span></span> {</span><br><span class="line">item := s.items[<span class="number">0</span>] <span class="comment">//先进先出</span></span><br><span class="line">s.items = s.items[<span class="number">1</span>:]</span><br><span class="line"><span class="keyword">return</span> &item</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *Queue)</span> <span class="title">IsEmpty</span><span class="params">()</span> <span class="title">bool</span></span> {</span><br><span class="line"><span class="keyword">return</span> <span class="built_in">len</span>(s.items) == <span class="number">0</span><span class="comment">//队列是否为空</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(s *Queue)</span> <span class="title">Size</span><span class="params">()</span> <span class="title">int</span></span> {</span><br><span class="line"><span class="keyword">return</span> <span class="built_in">len</span>(s.items)<span class="comment">//队列长度</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><h3 id="路径处理"><a href="#路径处理" class="headerlink" title="路径处理"></a>路径处理</h3><p>我们知道,所有的文件夹或者文件都是一个个<code>field</code>,那么,我们需要处理对应的路径关系,毕竟不能将所有有层级关系的资料都下载到同一个目录,这会给查找资料带来大麻烦。这里之前的<code>ParentId</code>派上用场了。</p><h4 id="结构"><a href="#结构" class="headerlink" title="结构"></a>结构</h4><p>我们需要将所有的<code>field</code>的父节点记录下来,将该节点的名称记录下来。所有我们有了如下结构。</p><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Path <span class="keyword">struct</span> {</span><br><span class="line">node <span class="keyword">map</span>[<span class="keyword">int</span>]<span class="keyword">string</span> <span class="comment">//节点 当前节点id 对应信息,可修改为interface{}复杂类型,这里只需要name选项,则string可满足</span></span><br><span class="line">relation <span class="keyword">map</span>[<span class="keyword">int</span>]<span class="keyword">int</span> <span class="comment">//关系 当前节点的父节点</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><h4 id="初始化方法"><a href="#初始化方法" class="headerlink" title="初始化方法"></a>初始化方法</h4><p>因为我们的结构体内使用了<code>map</code>类型,所以我们需要初始化一下,否则直接设置值会导致<code>nil</code>的属性无法被赋值。</p><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(p *Path)</span> <span class="title">New</span><span class="params">()</span> *<span class="title">Path</span></span> {</span><br><span class="line">p.node = <span class="keyword">map</span>[<span class="keyword">int</span>]<span class="keyword">string</span>{</span><br><span class="line"><span class="number">-1</span>: <span class="string">"download"</span>,<span class="comment">//设置一个 -1 的节点信息,后面将所有内容都保存在这个目录里</span></span><br><span class="line">}</span><br><span class="line">p.relation = <span class="keyword">map</span>[<span class="keyword">int</span>]<span class="keyword">int</span>{}</span><br><span class="line"><span class="keyword">return</span> p</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><h4 id="所有方法"><a href="#所有方法" class="headerlink" title="所有方法"></a>所有方法</h4><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> Path <span class="keyword">struct</span> {</span><br><span class="line">node <span class="keyword">map</span>[<span class="keyword">int</span>]<span class="keyword">string</span> </span><br><span class="line">relation <span class="keyword">map</span>[<span class="keyword">int</span>]<span class="keyword">int</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(p *Path)</span> <span class="title">New</span><span class="params">()</span> *<span class="title">Path</span></span> {</span><br><span class="line">p.node = <span class="keyword">map</span>[<span class="keyword">int</span>]<span class="keyword">string</span>{</span><br><span class="line"><span class="number">-1</span>: <span class="string">"download"</span>,</span><br><span class="line">}</span><br><span class="line">p.relation = <span class="keyword">map</span>[<span class="keyword">int</span>]<span class="keyword">int</span>{}</span><br><span class="line"><span class="keyword">return</span> p</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(p *Path)</span> <span class="title">Set</span><span class="params">(field *Field)</span></span> {<span class="comment">//将信息存入路径处理块内</span></span><br><span class="line"><span class="keyword">if</span> field.ParentId == <span class="string">""</span> {</span><br><span class="line">field.ParentId = <span class="string">"-1"</span><span class="comment">//将顶级目录加入父节点 -1</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">p.node[field.Id] = field.Name</span><br><span class="line">parentId, _ := strconv.Atoi(field.ParentId)<span class="comment">//转换string为int类型</span></span><br><span class="line">p.relation[field.Id] = parentId</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(p *Path)</span> <span class="title">Get</span><span class="params">(field *Field)</span> *<span class="title">Field</span></span> {<span class="comment">//传入field的指针,返回field指针</span></span><br><span class="line"><span class="keyword">var</span> chain []<span class="keyword">string</span></span><br><span class="line"><span class="keyword">var</span> buffer bytes.Buffer</span><br><span class="line"><span class="keyword">var</span> queryId <span class="keyword">int</span></span><br><span class="line"></span><br><span class="line">queryId = field.Id</span><br><span class="line"><span class="keyword">for</span> p.relation[queryId] != <span class="number">0</span> {<span class="comment">//根据已存入的信息查询当前field的所有关联节点</span></span><br><span class="line">queryId = p.relation[queryId]</span><br><span class="line">chain = <span class="built_in">append</span>(chain, p.node[queryId])</span><br><span class="line">}</span><br><span class="line"><span class="keyword">for</span> i := <span class="built_in">len</span>(chain) - <span class="number">1</span>; i > <span class="number">-1</span>; i-- {<span class="comment">//根据逆向查询的链式节点合成为路径</span></span><br><span class="line">buffer.WriteString(chain[i] + <span class="string">"/"</span>)</span><br><span class="line">}</span><br><span class="line">field.Path = buffer.String()</span><br><span class="line"><span class="keyword">return</span> field</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><h3 id="请求封装"><a href="#请求封装" class="headerlink" title="请求封装"></a>请求封装</h3><p>因为大部分请求都类似,所以我们可以进行一个简单的封装。</p><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Fetch</span><span class="params">(config *Config, url <span class="keyword">string</span>, auth <span class="keyword">bool</span>)</span> *<span class="title">http</span>.<span class="title">Response</span></span> {</span><br><span class="line">req, err := http.NewRequest(http.MethodGet, url, <span class="literal">nil</span>)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"><span class="built_in">panic</span>(err)</span><br><span class="line">}</span><br><span class="line"><span class="keyword">if</span> auth {<span class="comment">//设置授权头,如果请求涉及到第三方网站,比如下载,这里不设置,避免出错</span></span><br><span class="line">req.Header.Set(<span class="string">"Authorization"</span>, config.auth)</span><br><span class="line">}</span><br><span class="line">req.Header.Set(<span class="string">"User-Agent"</span>, config.userAgent)</span><br><span class="line">req.Header.Set(<span class="string">"Referer"</span>, config.referer)</span><br><span class="line"></span><br><span class="line">resp, err := http.DefaultClient.Do(req)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"><span class="built_in">panic</span>(err)</span><br><span class="line">}</span><br><span class="line"><span class="keyword">return</span> resp</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><h3 id="Field获取"><a href="#Field获取" class="headerlink" title="Field获取"></a>Field获取</h3><p>通过文件夹id获取该文件下的内容:</p><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//根据响应内容格式编写对应的结构体,方便json反序列化</span></span><br><span class="line"><span class="keyword">type</span> FieldResponseData <span class="keyword">struct</span> {</span><br><span class="line">Stat <span class="keyword">string</span> <span class="string">`json:"stat"`</span></span><br><span class="line">Data <span class="keyword">struct</span> {</span><br><span class="line">Data []Field <span class="string">`json:"data"`</span></span><br><span class="line">} <span class="string">`json:"data"`</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">getField</span><span class="params">(field *Field, config *Config)</span> []<span class="title">Field</span></span> {</span><br><span class="line">baseUrl := <span class="string">"https://example.com/api/listdir?page=1&per_page=100&showcenter=1&dirid="</span></span><br><span class="line">resp := Fetch(config, baseUrl+strconv.Itoa(field.Id), <span class="literal">true</span>)</span><br><span class="line"><span class="keyword">defer</span> resp.Body.Close()</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> resp.StatusCode != <span class="number">200</span> {</span><br><span class="line">fmt.Println(baseUrl+strconv.Itoa(field.Id), <span class="string">" 请求出错 "</span>, resp.StatusCode)</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">fetch, _ := ioutil.ReadAll(resp.Body)<span class="comment">//读取body的内容</span></span><br><span class="line">FieldData := &FieldResponseData{}</span><br><span class="line"><span class="keyword">if</span> err := json.Unmarshal(fetch, FieldData); err != <span class="literal">nil</span> {</span><br><span class="line"><span class="built_in">panic</span>(err)</span><br><span class="line">}</span><br><span class="line"><span class="keyword">return</span> FieldData.Data.Data</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>这里值得注意的一点是,请求的内容体比较小,使用<code>ioutil.ReadAll()</code>读取没什么问题,但是当下载大文件的时候,这里使用这个方法会占用大量的内存,因为,这个方法会将所有的数据读取到内存中,读取完毕后再一次性写入文件。 请求的内容体很大的时候,比如下载大文件,这里应当使用<code>io.copy</code>方法。这个方法会使用默认的32k缓存区,持续的将流复制到文件。</p><h3 id="队列循环任务"><a href="#队列循环任务" class="headerlink" title="队列循环任务"></a>队列循环任务</h3><p>队列应当怎么开始任务,怎样才算结束任务,怎么循环处理。</p><p>我们可以大致使用下面的方法来循环处理队列</p><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> _, v := <span class="keyword">range</span> getStart(config) {<span class="comment">//先请求顶级目录数据,将field插入队列</span></span><br><span class="line">queue.Put(v)</span><br><span class="line">}</span><br><span class="line">fmt.Printf(<span class="string">"初始入口数据 %d 条 \n"</span>, queue.Size())</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> queue.Size() != <span class="number">0</span> {<span class="comment">//当队列不为空,循环处理</span></span><br><span class="line">field := queue.Get() <span class="comment">//队列顶部取出任务</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> field.Type == <span class="string">""</span> {</span><br><span class="line"><span class="keyword">continue</span> <span class="comment">//可能存在空文件夹,直接跳过</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">path.Set(field) <span class="comment">//将field设置到路径地图</span></span><br><span class="line"><span class="keyword">if</span> field.Type == <span class="string">"dir"</span> { <span class="comment">// 文件夹 再请求field</span></span><br><span class="line"><span class="keyword">for</span> _, v := <span class="keyword">range</span> getField(field, config) {<span class="comment">//将获得的field插入队列尾部</span></span><br><span class="line">queue.Put(v)</span><br><span class="line">}</span><br><span class="line">fmt.Printf(<span class="string">"队列增加,目前有 %d 个field \n"</span>, queue.Size())</span><br><span class="line">} <span class="keyword">else</span> {<span class="comment">//下载field</span></span><br><span class="line">fmt.Printf(<span class="string">"队列下载,目前有 %d 个field \n"</span>, queue.Size())</span><br><span class="line">downloadField(path.Get(field), config)</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>其他没介绍的方法,大致都跟field请求类似,都可以自己实现。没有给出完整代码只是因为意义不大,毕竟不大可能有同样的需求。授人以鱼不如授人以渔。</p><p>扩展尝试:多线程处理队列任务。</p>]]></content>
<summary type="html">
<blockquote>
<p>起因是朋友月底要离职了,然后待的公司在系统里还有一些资料,想下载下来。手动一条一条下载太麻烦了,所以就找我帮忙看能不能用更科学的方法下载这些资料。</p>
<p>其实说是爬虫,不如说是一个自动采集下载的工具,其中,并没有实现分析网页源数据的功能,只是单纯的下载“公开”的数据。</p>
</blockquote>
</summary>
<category term="study" scheme="https://sevth.com/categories/study/"/>
<category term="golang" scheme="https://sevth.com/categories/study/golang/"/>
<category term="golang" scheme="https://sevth.com/tags/golang/"/>
<category term="spider" scheme="https://sevth.com/tags/spider/"/>
</entry>
<entry>
<title>对golang POST请求的封装</title>
<link href="https://sevth.com/study/golang/%E5%AF%B9golang%20POST%E8%AF%B7%E6%B1%82%E7%9A%84%E5%B0%81%E8%A3%85.html"/>
<id>https://sevth.com/study/golang/%E5%AF%B9golang%20POST%E8%AF%B7%E6%B1%82%E7%9A%84%E5%B0%81%E8%A3%85.html</id>
<published>2020-05-12T05:00:37.000Z</published>
<updated>2020-05-12T06:05:55.131Z</updated>
<content type="html"><![CDATA[<h2 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面"></a>写在前面</h2><blockquote><p>记录一下对<code>golang</code>自带的<code>net/http</code>包<code>POST</code>请求的封装。此处使用的常规表单模拟的方法,可以传入文件与表单项,使用上更方便一些。这里仅提供一个思路及表单构造的一些方法,更多的使用说明应该参考官方文档。当然,你也可以修改为更适合你自己的方法。</p><p><em>注意: 此处并没有提供上下文的支持,如果需要,应当自行修改。</em></p></blockquote><a id="more"></a><h2 id="入口方法"><a href="#入口方法" class="headerlink" title="入口方法"></a>入口方法</h2><p>构造一个<code>POST</code>请求,传入一些构造请求的参数,返回一个指向<code>postRequest</code>的指针。</p><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewPost</span><span class="params">(c *PostRequestInputConfig)</span> <span class="params">(*postRequest, error)</span></span></span><br></pre></td></tr></table></figure></div><ul><li>postRequest</li></ul><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> postRequest <span class="keyword">struct</span> {</span><br><span class="line">client *http.Client</span><br><span class="line">req *http.Request</span><br><span class="line">resp http.Response</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(r *postRequest)</span> <span class="title">SetHeader</span><span class="params">(name, value <span class="keyword">string</span>)</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(r *postRequest)</span> <span class="title">AddHeader</span><span class="params">(name, value <span class="keyword">string</span>)</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(r *postRequest)</span> <span class="title">Send</span><span class="params">()</span> <span class="params">(*http.Response, error)</span></span></span><br></pre></td></tr></table></figure></div><ul><li>PostRequestInputConfig</li></ul><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> PostRequestInputConfig <span class="keyword">struct</span> {</span><br><span class="line">Url <span class="keyword">string</span></span><br><span class="line">Proxy <span class="keyword">string</span></span><br><span class="line">Client *http.Client</span><br><span class="line">Body *PostRequestBodyField</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> PostRequestBodyField <span class="keyword">struct</span> {</span><br><span class="line">file <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">string</span></span><br><span class="line">field <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">string</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><ol><li>Url: 请求的地址</li><li>Proxy:使用代理,不使用留空即可</li><li>Client:自定义client</li><li>Body:表单内容,为<code>PostRequestBodyField</code>类型。使用两个<code>map</code>类型,无值请留空</li></ol><h2 id="使用参考"><a href="#使用参考" class="headerlink" title="使用参考"></a>使用参考</h2><p>详见<a href="/go/?K"><code>github</code></a></p><p>一个栗子:</p><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">post, err := NewPost(&PostRequestInputConfig{</span><br><span class="line">Url: <span class="string">"https://sm.ms/api/v2/upload"</span>,</span><br><span class="line"> <span class="comment">//Proxy: "socks5://127.0.0.1:1080",</span></span><br><span class="line"><span class="comment">//Client: nil,//自定义client,不使用无需设置此项</span></span><br><span class="line">Body: &PostRequestBodyField{</span><br><span class="line">file: <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">string</span>{<span class="string">"smfile"</span>: info.filePath},<span class="comment">//文件 key 与文件路径</span></span><br><span class="line">field: <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">string</span>{<span class="string">"format"</span>: <span class="string">"json"</span>},<span class="comment">//表单 key 与 value</span></span><br><span class="line">},</span><br><span class="line">})</span><br><span class="line"></span><br><span class="line">post.SetHeader(<span class="string">"Authorization"</span>, <span class="string">"token*************"</span>)</span><br><span class="line"></span><br><span class="line">resp, err := post.Send()</span><br><span class="line"><span class="keyword">defer</span> resp.Body.Close()</span><br></pre></td></tr></table></figure></div><h2 id="完整代码"><a href="#完整代码" class="headerlink" title="完整代码"></a>完整代码</h2><p><a href="/go/?l">github</a> or 如下:</p><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * Copyright (c) 2020. sevth <sevthdev@gmail.com></span></span><br><span class="line"><span class="comment"> * Project name: Tool, File name: http_Post.go</span></span><br><span class="line"><span class="comment"> * Date: 2020/5/6 下午1:03</span></span><br><span class="line"><span class="comment"> * Author: sevth</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">package</span> golang</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"><span class="string">"bytes"</span></span><br><span class="line"><span class="string">"errors"</span></span><br><span class="line"><span class="string">"io"</span></span><br><span class="line"><span class="string">"mime/multipart"</span></span><br><span class="line"><span class="string">"net/http"</span></span><br><span class="line"><span class="string">"net/url"</span></span><br><span class="line"><span class="string">"os"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> postRequest <span class="keyword">struct</span> {</span><br><span class="line">client *http.Client</span><br><span class="line">req *http.Request</span><br><span class="line">resp http.Response</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> PostRequestInputConfig <span class="keyword">struct</span> {</span><br><span class="line">Url <span class="keyword">string</span></span><br><span class="line">Proxy <span class="keyword">string</span></span><br><span class="line">Client *http.Client</span><br><span class="line">Body *PostRequestBodyField</span><br><span class="line">}</span><br><span class="line"><span class="keyword">type</span> PostRequestBodyField <span class="keyword">struct</span> {</span><br><span class="line">file <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">string</span></span><br><span class="line">field <span class="keyword">map</span>[<span class="keyword">string</span>]<span class="keyword">string</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">NewPost</span><span class="params">(c *PostRequestInputConfig)</span> <span class="params">(*postRequest, error)</span></span> {</span><br><span class="line"><span class="keyword">var</span> err error</span><br><span class="line">r := &postRequest{}</span><br><span class="line"><span class="comment">// 检测url情况</span></span><br><span class="line"><span class="keyword">if</span> c.Url == <span class="string">""</span> {</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span>, errors.New(<span class="string">"url is not set"</span>)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> c.Proxy != <span class="string">""</span> {</span><br><span class="line">r.client = &http.Client{Transport: &http.Transport{</span><br><span class="line">Proxy: <span class="function"><span class="keyword">func</span><span class="params">(_ *http.Request)</span> <span class="params">(*url.URL, error)</span></span> {</span><br><span class="line"><span class="keyword">return</span> url.Parse(c.Proxy)</span><br><span class="line">},</span><br><span class="line">}}</span><br><span class="line">}</span><br><span class="line"><span class="comment">// 自定义client权重更高,设置了client的话,再设置proxy无效</span></span><br><span class="line"><span class="keyword">if</span> r.client == <span class="literal">nil</span> {</span><br><span class="line">r.client = &http.Client{}</span><br><span class="line">}</span><br><span class="line"><span class="keyword">if</span> c.Client != <span class="literal">nil</span> {</span><br><span class="line">r.client = c.Client</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">body := &bytes.Buffer{}</span><br><span class="line">bw := multipart.NewWriter(body)</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> keyName, fp := <span class="keyword">range</span> c.Body.file {</span><br><span class="line">fw, err := bw.CreateFormFile(keyName, fp)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line"><span class="comment">//fmt.Println(err)</span></span><br><span class="line">}</span><br><span class="line">fd, err := os.Open(fp)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line"><span class="comment">//fmt.Println(err)</span></span><br><span class="line">}</span><br><span class="line">_, err = io.Copy(fw, fd)</span><br><span class="line">fd.Close()</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> k, v := <span class="keyword">range</span> c.Body.field {</span><br><span class="line">err := bw.WriteField(k, v)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line"><span class="comment">//fmt.Println(err)</span></span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">_ = bw.Close() <span class="comment">// 写完数据直接关闭,不然数据长度校验会出错</span></span><br><span class="line"></span><br><span class="line">r.req, err = http.NewRequest(<span class="string">"POST"</span>, c.Url, body)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">}</span><br><span class="line">r.req.Header.Set(<span class="string">"Content-Type"</span>, bw.FormDataContentType())</span><br><span class="line"><span class="keyword">return</span> r, <span class="literal">nil</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(r *postRequest)</span> <span class="title">SetHeader</span><span class="params">(name, value <span class="keyword">string</span>)</span></span> {</span><br><span class="line">r.req.Header.Set(name, value)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(r *postRequest)</span> <span class="title">AddHeader</span><span class="params">(name, value <span class="keyword">string</span>)</span></span> {</span><br><span class="line">r.req.Header.Add(name, value)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(r *postRequest)</span> <span class="title">Send</span><span class="params">()</span> <span class="params">(*http.Response, error)</span></span> {</span><br><span class="line">resp, err := r.client.Do(r.req)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span>, err</span><br><span class="line">}</span><br><span class="line"><span class="keyword">return</span> resp, <span class="literal">nil</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>]]></content>
<summary type="html">
<h2 id="写在前面"><a href="#写在前面" class="headerlink" title="写在前面"></a>写在前面</h2><blockquote>
<p>记录一下对<code>golang</code>自带的<code>net/http</code>包<code>POST</code>请求的封装。此处使用的常规表单模拟的方法,可以传入文件与表单项,使用上更方便一些。这里仅提供一个思路及表单构造的一些方法,更多的使用说明应该参考官方文档。当然,你也可以修改为更适合你自己的方法。</p>
<p><em>注意: 此处并没有提供上下文的支持,如果需要,应当自行修改。</em></p>
</blockquote>
</summary>
<category term="study" scheme="https://sevth.com/categories/study/"/>
<category term="golang" scheme="https://sevth.com/categories/study/golang/"/>
<category term="golang" scheme="https://sevth.com/tags/golang/"/>
<category term="net/http" scheme="https://sevth.com/tags/net-http/"/>
</entry>
<entry>
<title>aws-go-sdk并发分片上传封装</title>
<link href="https://sevth.com/study/golang/aws-go-sdk%E5%B9%B6%E5%8F%91%E5%88%86%E7%89%87%E4%B8%8A%E4%BC%A0%E5%B0%81%E8%A3%85.html"/>
<id>https://sevth.com/study/golang/aws-go-sdk%E5%B9%B6%E5%8F%91%E5%88%86%E7%89%87%E4%B8%8A%E4%BC%A0%E5%B0%81%E8%A3%85.html</id>
<published>2020-05-07T02:21:08.000Z</published>
<updated>2020-05-07T03:26:38.750Z</updated>
<content type="html"><![CDATA[<blockquote><p>目前的话,aws 官方的go sdk只提供了分片的操作方法,具体的实现还得自己去组合方法,网上能够找到很多相关的例子,但是我觉得都不太<code>性能</code>或者太复杂,这里我只是对分片上传包装了一下,上传是异步的,如果需要同步可以自己拆分一下</p></blockquote><a id="more"></a><h2 id="相关接口"><a href="#相关接口" class="headerlink" title="相关接口"></a>相关接口</h2><ul><li>创建分片上传</li></ul><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *S3)</span> <span class="title">CreateMultipartUpload</span><span class="params">(input *CreateMultipartUploadInput)</span></span></span><br></pre></td></tr></table></figure></div><ul><li>上传单个分片</li></ul><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *S3)</span> <span class="title">UploadPart</span><span class="params">(input *UploadPartInput)</span> <span class="params">(*UploadPartOutput, error)</span></span></span><br></pre></td></tr></table></figure></div><ul><li>分片上传完成,通知合成文件</li></ul><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *S3)</span> <span class="title">CompleteMultipartUpload</span><span class="params">(input *CompleteMultipartUploadInput)</span></span></span><br></pre></td></tr></table></figure></div><ul><li>中分片上传 (上传失败调用来删除已上传的分片)</li></ul><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(c *S3)</span> <span class="title">AbortMultipartUpload</span><span class="params">(input *AbortMultipartUploadInput)</span> <span class="params">(*AbortMultipartUploadOutput, error)</span></span></span><br></pre></td></tr></table></figure></div><h2 id="文档入口方法"><a href="#文档入口方法" class="headerlink" title="文档入口方法"></a>文档入口方法</h2><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(a *AwsMultiPartUpload)</span> <span class="title">AwsMultipartUpload</span><span class="params">(svc *s3.S3)</span> <span class="title">error</span></span></span><br></pre></td></tr></table></figure></div><h2 id=""><a href="#" class="headerlink" title=""></a></h2><h2 id="使用例子"><a href="#使用例子" class="headerlink" title="使用例子"></a>使用例子</h2><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">func main() {</span><br><span class="line">sess := session.Must(session.NewSession(&aws.Config{</span><br><span class="line">Endpoint: aws.String(Endpoint),//地域</span><br><span class="line">Region: aws.String(region),//地区</span><br><span class="line">DisableSSL: aws.Bool(false),// ssl支持</span><br><span class="line">Credentials: credentials.NewStaticCredentials(AccessKeyId, AccessKeySecret, ""),//令牌</span><br><span class="line">}))</span><br><span class="line"></span><br><span class="line">svc := s3.New(sess)</span><br><span class="line"></span><br><span class="line">// 需要引入文件或者直接复制使用</span><br><span class="line">upload := &AwsMultiPartUpload{</span><br><span class="line">Bucket: BucketName,</span><br><span class="line">FilePath: filePath,</span><br><span class="line">FileSize: fileSize,</span><br><span class="line">FileKey: fileKey,</span><br><span class="line">FileMime: fileMime,</span><br><span class="line">PartSize: partSize,</span><br><span class="line">}</span><br><span class="line">err = upload.AwsMultipartUpload(svc)</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><h2 id="结构数据"><a href="#结构数据" class="headerlink" title="结构数据"></a>结构数据</h2><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">type</span> AwsMultiPartUpload <span class="keyword">struct</span> {</span><br><span class="line">Bucket <span class="keyword">string</span></span><br><span class="line">FilePath <span class="keyword">string</span></span><br><span class="line">FileKey <span class="keyword">string</span></span><br><span class="line">FileMime <span class="keyword">string</span></span><br><span class="line">FileSize <span class="keyword">int64</span></span><br><span class="line">PartSize <span class="keyword">int64</span> <span class="comment">// 分片大小</span></span><br><span class="line">chunkCount <span class="keyword">int</span> <span class="comment">// 分块个数</span></span><br><span class="line">Tries <span class="keyword">int</span> <span class="comment">// 单个分片上传尝试次数</span></span><br><span class="line">Goroutine <span class="keyword">int</span> <span class="comment">// 线程</span></span><br><span class="line">CompletedParts []*s3.CompletedPart <span class="comment">// 保存分片数据</span></span><br><span class="line">mux sync.Mutex</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>所有的方法接受者均为 <code>AwsMultiPartUpload</code>, 所以需要先初始化数据 <code>upload := &AwsMultiPartUpload</code> 与 <code>upload := new(AwsMultiPartUpload)</code> 是一样的。</p><h3 id="并发线程"><a href="#并发线程" class="headerlink" title="并发线程"></a>并发线程</h3><p>默认是八个,需要更多线程完全可以自己修改。</p><h3 id="单个分片上传重试"><a href="#单个分片上传重试" class="headerlink" title="单个分片上传重试"></a>单个分片上传重试</h3><p>默认重试次数为3,这个也可以在修改的时候直接设置</p><h3 id="分块大小"><a href="#分块大小" class="headerlink" title="分块大小"></a>分块大小</h3><p>就是分片上传切分成多大一个的块,默认是 4M,这个也可以设置</p><h2 id="实现方法代码"><a href="#实现方法代码" class="headerlink" title="实现方法代码"></a>实现方法代码</h2><p>见<a href="https://github.com/sevth-developer/tools/blob/master/golang/Aws分片上传(并发).go"><code>github</code></a> 或者如下</p><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> golang</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"><span class="string">"bytes"</span></span><br><span class="line"><span class="string">"errors"</span></span><br><span class="line"><span class="string">"github.com/aws/aws-sdk-go/aws"</span></span><br><span class="line"><span class="string">"github.com/aws/aws-sdk-go/aws/awserr"</span></span><br><span class="line"><span class="string">"github.com/aws/aws-sdk-go/service/s3"</span></span><br><span class="line"><span class="string">"io/ioutil"</span></span><br><span class="line"><span class="string">"math"</span></span><br><span class="line"><span class="string">"os"</span></span><br><span class="line"><span class="string">"sync"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> AwsMultiPartUpload <span class="keyword">struct</span> {</span><br><span class="line">Bucket <span class="keyword">string</span></span><br><span class="line">FilePath <span class="keyword">string</span></span><br><span class="line">FileKey <span class="keyword">string</span></span><br><span class="line">FileMime <span class="keyword">string</span></span><br><span class="line">FileSize <span class="keyword">int64</span></span><br><span class="line">PartSize <span class="keyword">int64</span> <span class="comment">// 分片大小</span></span><br><span class="line">chunkCount <span class="keyword">int</span> <span class="comment">// 分块个数</span></span><br><span class="line">Tries <span class="keyword">int</span> <span class="comment">// 单个分片上传尝试次数</span></span><br><span class="line">Goroutine <span class="keyword">int</span> <span class="comment">// 线程</span></span><br><span class="line">CompletedParts []*s3.CompletedPart <span class="comment">// 保存分片数据</span></span><br><span class="line">mux sync.Mutex</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//func NewAwsMultiPartUpload() *AwsMultiPartUpload {</span></span><br><span class="line"><span class="comment">//return &AwsMultiPartUpload{</span></span><br><span class="line"><span class="comment">//Goroutine: 8,</span></span><br><span class="line"><span class="comment">//Tries: 3,</span></span><br><span class="line"><span class="comment">//PartSize: 1 * 1024 * 1024,</span></span><br><span class="line"><span class="comment">//}</span></span><br><span class="line"><span class="comment">//}</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(a *AwsMultiPartUpload)</span> <span class="title">AwsMultipartUpload</span><span class="params">(svc *s3.S3)</span> <span class="title">error</span></span> {</span><br><span class="line"><span class="keyword">if</span> <span class="number">16</span> < a.Goroutine || <span class="number">0</span> >= a.Goroutine {</span><br><span class="line">a.Goroutine = <span class="number">8</span> <span class="comment">// 不允许设置过大</span></span><br><span class="line">}</span><br><span class="line"><span class="keyword">if</span> a.Bucket == <span class="string">""</span> || a.FilePath == <span class="string">""</span> {</span><br><span class="line"><span class="keyword">return</span> errors.New(<span class="string">"未设置必须参数"</span>)</span><br><span class="line">}</span><br><span class="line"><span class="keyword">if</span> a.Tries == <span class="number">0</span> {</span><br><span class="line">a.Tries = <span class="number">3</span></span><br><span class="line">}</span><br><span class="line"><span class="keyword">if</span> a.PartSize == <span class="number">0</span> {</span><br><span class="line">a.PartSize = <span class="number">4</span> * <span class="number">1024</span> * <span class="number">1024</span></span><br><span class="line">}</span><br><span class="line"><span class="keyword">if</span> svc == <span class="literal">nil</span> {</span><br><span class="line"><span class="keyword">return</span> errors.New(<span class="string">"svc 错误"</span>)</span><br><span class="line">}</span><br><span class="line">a.chunkCount = a.divideCeil(a.FileSize, a.PartSize) <span class="comment">// 分块个数</span></span><br><span class="line"><span class="keyword">if</span> <span class="built_in">len</span>(a.CompletedParts) == <span class="number">0</span> { <span class="comment">//初始化切片,长度为分块个数,后面分片排序需要用到</span></span><br><span class="line">a.CompletedParts = <span class="built_in">make</span>([]*s3.CompletedPart, a.chunkCount)</span><br><span class="line">}</span><br><span class="line"><span class="keyword">return</span> a.awsMultiPartUpload(svc)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(a *AwsMultiPartUpload)</span> <span class="title">awsMultiPartUpload</span><span class="params">(svc *s3.S3)</span> <span class="title">error</span></span> {</span><br><span class="line">file, err := os.Open(a.FilePath)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">}</span><br><span class="line"><span class="keyword">defer</span> file.Close()</span><br><span class="line">buffer := <span class="built_in">make</span>([]<span class="keyword">byte</span>, a.FileSize) <span class="comment">// 使用一个文件大小长度的byte切片存储上传的文件数据</span></span><br><span class="line">buffer, _ = ioutil.ReadAll(file) <span class="comment">// ioutil 读取速度快!</span></span><br><span class="line"></span><br><span class="line">initData, err := a.initMultipartUpload(svc) <span class="comment">// 初始化分块</span></span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">}</span><br><span class="line">errChan := <span class="built_in">make</span>(<span class="keyword">chan</span> error, a.Goroutine) <span class="comment">// 创建通道</span></span><br><span class="line"><span class="keyword">for</span> i := <span class="number">0</span>; i != a.Goroutine; i++ { <span class="comment">//通道置空,阻塞八个并发</span></span><br><span class="line">errChan <- <span class="literal">nil</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">wg := &sync.WaitGroup{}</span><br><span class="line"><span class="keyword">for</span> i := <span class="number">0</span>; i != a.chunkCount; i++ {</span><br><span class="line"><span class="comment">//println(i)</span></span><br><span class="line">wg.Add(<span class="number">1</span>)</span><br><span class="line"><span class="keyword">go</span> <span class="function"><span class="keyword">func</span><span class="params">(pos <span class="keyword">int</span>)</span></span> { <span class="comment">// 第几个块,取偏移量</span></span><br><span class="line"><span class="keyword">defer</span> wg.Done() <span class="comment">// 完成分片,计数器减一</span></span><br><span class="line">start := a.PartSize * <span class="keyword">int64</span>(pos) <span class="comment">// 起始地址</span></span><br><span class="line">offset := a.PartSize * <span class="keyword">int64</span>(pos+<span class="number">1</span>) <span class="comment">// 偏移地址</span></span><br><span class="line"><span class="keyword">if</span> pos == a.chunkCount<span class="number">-1</span> { <span class="comment">// 最后一个块,偏移地址为文件长度</span></span><br><span class="line">offset = a.FileSize</span><br><span class="line">}</span><br><span class="line">err := a.uploadPart(svc, initData, buffer[start:offset], pos)</span><br><span class="line">errChan <- err</span><br><span class="line">}(i)</span><br><span class="line">uploadErr := <-errChan <span class="comment">// 接收通道值</span></span><br><span class="line"><span class="keyword">if</span> uploadErr != <span class="literal">nil</span> {</span><br><span class="line">err = uploadErr</span><br><span class="line"><span class="keyword">break</span> <span class="comment">//上传出错,需要取消上传</span></span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line">wg.Wait() <span class="comment">// 等待任务完成</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">select</span> { <span class="comment">//检查一下是否有剩余的通道未接收,然后检查</span></span><br><span class="line"><span class="keyword">case</span> e := <-errChan:</span><br><span class="line"><span class="keyword">if</span> e != <span class="literal">nil</span> {</span><br><span class="line">err = e</span><br><span class="line">}</span><br><span class="line"><span class="keyword">default</span>:</span><br><span class="line">err = <span class="literal">nil</span></span><br><span class="line">}</span><br><span class="line"><span class="built_in">close</span>(errChan) <span class="comment">// 关闭通道</span></span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> { <span class="comment">// 处理之前的错误</span></span><br><span class="line">_, err := a.abortMultipartUpload(svc, initData)</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"><span class="comment">//fmt.Println(resp)</span></span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">_, err = a.completeMultipartUpload(svc, initData, a.CompletedParts) <span class="comment">// 分片上传完成</span></span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 初始化分片上传</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(a *AwsMultiPartUpload)</span> <span class="title">initMultipartUpload</span><span class="params">(svc *s3.S3)</span> <span class="params">(*s3.CreateMultipartUploadOutput, error)</span></span> {</span><br><span class="line"><span class="keyword">return</span> svc.CreateMultipartUpload(&s3.CreateMultipartUploadInput{ <span class="comment">// 直接返回初始化分片上传的数据</span></span><br><span class="line">Bucket: aws.String(a.Bucket),</span><br><span class="line">Key: aws.String(a.FileKey),</span><br><span class="line">ContentType: aws.String(a.FileMime),</span><br><span class="line">})</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 上传单个分片</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(a *AwsMultiPartUpload)</span> <span class="title">uploadPart</span><span class="params">(svc *s3.S3, resp *s3.CreateMultipartUploadOutput, fileByte []<span class="keyword">byte</span>, pos <span class="keyword">int</span>)</span> <span class="params">(err error)</span></span> {</span><br><span class="line">tryNum := <span class="number">0</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> tryNum < a.Tries {</span><br><span class="line">uploadResult, err := svc.UploadPart(&s3.UploadPartInput{</span><br><span class="line">Body: bytes.NewReader(fileByte),</span><br><span class="line">Bucket: resp.Bucket,</span><br><span class="line">Key: resp.Key,</span><br><span class="line">PartNumber: aws.Int64(<span class="keyword">int64</span>(pos)),</span><br><span class="line">UploadId: resp.UploadId,</span><br><span class="line">ContentLength: aws.Int64(<span class="keyword">int64</span>(<span class="built_in">len</span>(fileByte))),</span><br><span class="line">})</span><br><span class="line"><span class="keyword">if</span> err != <span class="literal">nil</span> {</span><br><span class="line"><span class="keyword">if</span> tryNum == a.Tries {</span><br><span class="line"><span class="keyword">if</span> aerr, ok := err.(awserr.Error); ok {</span><br><span class="line"><span class="keyword">return</span> aerr</span><br><span class="line">}</span><br><span class="line"><span class="keyword">return</span> err</span><br><span class="line">}</span><br><span class="line"><span class="comment">//fmt.Printf("Retrying to upload part #%v\n", pos)</span></span><br><span class="line">tryNum++</span><br><span class="line">} <span class="keyword">else</span> {</span><br><span class="line">a.mux.Lock() <span class="comment">// 上锁,避免数据出错</span></span><br><span class="line">temp := &s3.CompletedPart{</span><br><span class="line">ETag: uploadResult.ETag,</span><br><span class="line">PartNumber: aws.Int64(<span class="keyword">int64</span>(pos)),</span><br><span class="line">}</span><br><span class="line">a.CompletedParts[pos] = temp</span><br><span class="line"><span class="comment">//println(a.CompletedParts[pos])</span></span><br><span class="line">a.mux.Unlock() <span class="comment">//解锁</span></span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span> <span class="comment">// 不返回的话会无限循环</span></span><br><span class="line">}</span><br><span class="line">}</span><br><span class="line"><span class="keyword">return</span> <span class="literal">nil</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 分片上传完成,请求完成</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(a *AwsMultiPartUpload)</span> <span class="title">completeMultipartUpload</span><span class="params">(svc *s3.S3, resp *s3.CreateMultipartUploadOutput, completedParts []*s3.CompletedPart)</span> <span class="params">(*s3.CompleteMultipartUploadOutput, error)</span></span> {</span><br><span class="line"><span class="keyword">return</span> svc.CompleteMultipartUpload(&s3.CompleteMultipartUploadInput{ <span class="comment">// 完成分片上传,发请求合成文件</span></span><br><span class="line">Bucket: resp.Bucket,</span><br><span class="line">Key: resp.Key,</span><br><span class="line">UploadId: resp.UploadId,</span><br><span class="line">MultipartUpload: &s3.CompletedMultipartUpload{Parts: completedParts},</span><br><span class="line">})</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 分片上传出错,中断上传</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(a *AwsMultiPartUpload)</span> <span class="title">abortMultipartUpload</span><span class="params">(svc *s3.S3, resp *s3.CreateMultipartUploadOutput)</span> <span class="params">(*s3.AbortMultipartUploadOutput, error)</span></span> {</span><br><span class="line"><span class="keyword">return</span> svc.AbortMultipartUpload(&s3.AbortMultipartUploadInput{ <span class="comment">// 分片上传失败调用取消分片上传</span></span><br><span class="line">Bucket: resp.Bucket,</span><br><span class="line">Key: resp.Key,</span><br><span class="line">UploadId: resp.UploadId,</span><br><span class="line">})</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="params">(a *AwsMultiPartUpload)</span> <span class="title">divideCeil</span><span class="params">(inta, intb <span class="keyword">int64</span>)</span> <span class="title">int</span></span> {</span><br><span class="line">div := <span class="keyword">float64</span>(inta) / <span class="keyword">float64</span>(intb)</span><br><span class="line">c := math.Ceil(div)</span><br><span class="line"><span class="keyword">return</span> <span class="keyword">int</span>(c)</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div>]]></content>
<summary type="html">
<blockquote>
<p>目前的话,aws 官方的go sdk只提供了分片的操作方法,具体的实现还得自己去组合方法,网上能够找到很多相关的例子,但是我觉得都不太<code>性能</code>或者太复杂,这里我只是对分片上传包装了一下,上传是异步的,如果需要同步可以自己拆分一下</p>
</blockquote>
</summary>
<category term="study" scheme="https://sevth.com/categories/study/"/>
<category term="golang" scheme="https://sevth.com/categories/study/golang/"/>
<category term="aws" scheme="https://sevth.com/tags/aws/"/>
<category term="分片上传" scheme="https://sevth.com/tags/%E5%88%86%E7%89%87%E4%B8%8A%E4%BC%A0/"/>
</entry>
<entry>
<title>golang 跨平台编译指南</title>
<link href="https://sevth.com/study/golang/golang%20%E8%B7%A8%E5%B9%B3%E5%8F%B0%E7%BC%96%E8%AF%91%E6%8C%87%E5%8D%97.html"/>
<id>https://sevth.com/study/golang/golang%20%E8%B7%A8%E5%B9%B3%E5%8F%B0%E7%BC%96%E8%AF%91%E6%8C%87%E5%8D%97.html</id>
<published>2020-05-02T14:36:06.000Z</published>
<updated>2020-05-02T18:10:20.398Z</updated>
<content type="html"><![CDATA[<blockquote><p>今日 <code>get</code> , <code>golang</code> 的跨平台编译</p></blockquote><a id="more"></a><h3 id="一些编译说明"><a href="#一些编译说明" class="headerlink" title="一些编译说明"></a>一些编译说明</h3><p>Golang 作为一门跨平台语言,编译的时候自然也是可以跨平台编译的。</p><p><code>Mac</code> 平台下跨平台编译其他平台应用:</p><div class="highlight-container"><figure class=" highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go//linux</span><br><span class="line">CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go// windows</span><br></pre></td></tr></table></figure></div><p>跨平台的编译操作都像上面的这个样子,我们来分析一下这一条代码的内容:</p><p> <code>CGO_ENABLED</code> :因为我们是跨平台编译,<code>go</code>并不支持<code>CGO</code>,所以我们需要关闭它。</p><p><code>GOOS</code> :这个是设置你要编译的平台,目前可选的有(darwin, freebsd, linux, windows)</p><p><code>GOARCH</code>: 这是目标系统的架构,比如(386, amd64, arm)。<code>386</code>就是32位的平台,<code>amd64</code>就是64位平台。</p><h3 id="各平台的一些区别"><a href="#各平台的一些区别" class="headerlink" title="各平台的一些区别"></a>各平台的一些区别</h3><p>在 <code>windows</code> 下,我们的编译指令有些不同,如下:</p><div class="highlight-container"><figure class=" highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">SET CGO_ENABLED=0</span><br><span class="line">SET GOOS=darwin</span><br><span class="line">SET GOARCH=amd64</span><br><span class="line">go build main.go//编译mac平台64位应用</span><br></pre></td></tr></table></figure></div><p>参数都是一样的,只不过<code>windows</code>下需要分四步输入才能编译,而对于<code>linux</code> 与 <code>mac</code>,它们的指令使用都是一致的,只需要一条即可交叉编译。</p><h3 id="一些注意的事情"><a href="#一些注意的事情" class="headerlink" title="一些注意的事情"></a>一些注意的事情</h3><p>比如我们编译的时候碰到下面这种</p><p><img src="https://img.sevth.com/test/2020/cXxrCLTSShxKEGIU.png" alt="image-20200503020400390"></p><p>其实仔细理一下错误,这就是缺少一些需要的包而已,我们可以直接使用<code>go get github.com/xxx/xxx</code> 的方式直接下载,如果下载存在问题,建议直接到<code>github</code>上手动下载,然后将包放到对应的文件位置,然后我们就可以编译通过了。</p>]]></content>
<summary type="html">
<blockquote>
<p>今日 <code>get</code> , <code>golang</code> 的跨平台编译</p>
</blockquote>
</summary>
<category term="study" scheme="https://sevth.com/categories/study/"/>
<category term="golang" scheme="https://sevth.com/categories/study/golang/"/>
<category term="golang" scheme="https://sevth.com/tags/golang/"/>
<category term="across platform" scheme="https://sevth.com/tags/across-platform/"/>
</entry>
<entry>
<title>golang:随机数的产生</title>
<link href="https://sevth.com/study/golang/golang%EF%BC%9A%E9%9A%8F%E6%9C%BA%E6%95%B0%E7%9A%84%E4%BA%A7%E7%94%9F.html"/>
<id>https://sevth.com/study/golang/golang%EF%BC%9A%E9%9A%8F%E6%9C%BA%E6%95%B0%E7%9A%84%E4%BA%A7%E7%94%9F.html</id>
<published>2020-04-29T07:43:37.000Z</published>
<updated>2020-04-29T08:01:37.268Z</updated>
<content type="html"><![CDATA[<blockquote><p>今日记录:随机数的产生与<code>随机</code></p></blockquote><a id="more"></a><h3 id="产生随机数的函数"><a href="#产生随机数的函数" class="headerlink" title="产生随机数的函数"></a>产生随机数的函数</h3><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Intn returns, as an int, a non-negative pseudo-random number in [0,n)</span></span><br><span class="line"><span class="comment">// from the default Source.</span></span><br><span class="line"><span class="comment">// It panics if n <= 0.</span></span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">Intn</span><span class="params">(n <span class="keyword">int</span>)</span> <span class="title">int</span></span> { <span class="keyword">return</span> globalRand.Intn(n) }</span><br></pre></td></tr></table></figure></div><p>这是官方文档的说明,这个函数根据返回一个输入<code>进制</code>随机数。</p><p>然而在我们的实际使用中,这个随机数产生的随机数变得固定了,也就是说不随机了。</p><p>做个测试:</p><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line"><span class="keyword">for</span> i := <span class="number">0</span>; i < <span class="number">10</span>; i++ {</span><br><span class="line">num := rand.Intn(<span class="number">10</span>)<span class="comment">//十进制随机数</span></span><br><span class="line">fmt.Printf(<span class="string">"num=%d\n"</span>, num)</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>结果如下:</p><p><img src="https://img.sevth.com/website/2020/04/29/893ebcd45142f5915021708fa4c7db17.png" alt="image-20200429155503781"></p><p>看起来似乎是随机了,然鹅你运行多次发现,打印的数据每次运行都是相同的,连顺序都一样。</p><p>这是因为程序编译后,运行的环境是固定的,所以随机数产生后不再变化。</p><h3 id="加入随机种子"><a href="#加入随机种子" class="headerlink" title="加入随机种子"></a>加入随机种子</h3><p>加入随机种子可以解决随机数不随机的问题</p><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line">rand.Seed(time.Now().UnixNano())<span class="comment">//加入随机种子</span></span><br><span class="line"><span class="keyword">for</span> i := <span class="number">0</span>; i < <span class="number">10</span>; i++ {</span><br><span class="line">num := rand.Intn(<span class="number">10</span>)</span><br><span class="line">fmt.Printf(<span class="string">"num=%d\n"</span>, num)</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>此时,随机数的产生就真的随机了,不再是固定的随机数。</p><h3 id="关键代码"><a href="#关键代码" class="headerlink" title="关键代码"></a>关键代码</h3><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rand.Seed(time.Now().UnixNano())</span><br></pre></td></tr></table></figure></div>]]></content>
<summary type="html">
<blockquote>
<p>今日记录:随机数的产生与<code>随机</code></p>
</blockquote>
</summary>
<category term="study" scheme="https://sevth.com/categories/study/"/>
<category term="golang" scheme="https://sevth.com/categories/study/golang/"/>
<category term="golang" scheme="https://sevth.com/tags/golang/"/>
<category term="rand" scheme="https://sevth.com/tags/rand/"/>
</entry>
<entry>
<title>golang获取结构体属性个数</title>
<link href="https://sevth.com/study/golang/golang%EF%BC%9A%E8%8E%B7%E5%8F%96%E7%BB%93%E6%9E%84%E4%BD%93%E5%B1%9E%E6%80%A7%E4%B8%AA%E6%95%B0.html"/>
<id>https://sevth.com/study/golang/golang%EF%BC%9A%E8%8E%B7%E5%8F%96%E7%BB%93%E6%9E%84%E4%BD%93%E5%B1%9E%E6%80%A7%E4%B8%AA%E6%95%B0.html</id>
<published>2020-04-28T12:32:45.000Z</published>
<updated>2020-04-28T12:45:49.186Z</updated>
<content type="html"><![CDATA[<blockquote><p>快速解疑碰到的问题</p><p><code>golang</code> 学习积累</p></blockquote><a id="more"></a><h3 id="使用-reflect-来获取结构体的属性个数"><a href="#使用-reflect-来获取结构体的属性个数" class="headerlink" title="使用 reflect 来获取结构体的属性个数"></a>使用 <code>reflect</code> 来获取结构体的属性个数</h3><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> main</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> (</span><br><span class="line"><span class="string">"fmt"</span></span><br><span class="line"><span class="string">"reflect"</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="keyword">type</span> Study <span class="keyword">struct</span> {</span><br><span class="line">name <span class="keyword">string</span></span><br><span class="line">age <span class="keyword">int8</span></span><br><span class="line">school <span class="keyword">string</span></span><br><span class="line">class []<span class="keyword">string</span></span><br><span class="line">}</span><br><span class="line"><span class="function"><span class="keyword">func</span> <span class="title">main</span><span class="params">()</span></span> {</span><br><span class="line">fmt.Println(reflect.ValueOf(Study{}).NumField())</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p><strong>结果如下</strong></p><p><img src="https://img.sevth.com/website/2020/04/28/30f78ab9236d3fdc307910f4d4ad07b6.png" alt="image-20200428204105350"></p><h3 id="关键代码"><a href="#关键代码" class="headerlink" title="关键代码"></a>关键代码</h3><div class="highlight-container"><figure class=" highlight go"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">reflect.ValueOf(<span class="keyword">struct</span>{}).NumField()</span><br></pre></td></tr></table></figure></div>]]></content>
<summary type="html">
<blockquote>
<p>快速解疑碰到的问题</p>
<p><code>golang</code> 学习积累</p>
</blockquote>
</summary>
<category term="study" scheme="https://sevth.com/categories/study/"/>
<category term="golang" scheme="https://sevth.com/categories/study/golang/"/>
<category term="golang" scheme="https://sevth.com/tags/golang/"/>
<category term="struct" scheme="https://sevth.com/tags/struct/"/>
</entry>
<entry>
<title>自制极简网页计数器</title>
<link href="https://sevth.com/develop/javascript/%E8%87%AA%E5%88%B6%E6%9E%81%E7%AE%80%E7%BD%91%E9%A1%B5%E8%AE%A1%E6%95%B0%E5%99%A8.html"/>
<id>https://sevth.com/develop/javascript/%E8%87%AA%E5%88%B6%E6%9E%81%E7%AE%80%E7%BD%91%E9%A1%B5%E8%AE%A1%E6%95%B0%E5%99%A8.html</id>
<published>2020-04-22T19:21:41.000Z</published>
<updated>2020-05-03T18:33:11.847Z</updated>
<content type="html"><![CDATA[<blockquote><p>因为懒,不想写过说明,直接从 <code>github</code> 上 copy 过来了,将就着看吧,因为是使用的 <code>Dom</code> 监听事件,所以,是不支持 <code>Pjax</code> 了,再然后,有一点小小的失误,里面用了箭头函数,也就是低版本的浏览器兼容性没做,改天有空再修改一下吧。</p><p>关于后台程序,有空会整理出来,最后,我只是一个小菜鸟,写的并不好。</p></blockquote><a id="more"></a><h1 id="counter-js"><a href="#counter-js" class="headerlink" title="counter_js"></a>counter_js</h1><p>使用 Lumen 作为后端开发的简易网页计数器,用于支持 <code>Hexo</code> 博客的 <code>uv</code>、<code>pv</code>统计。</p><h2 id="浏览器支持"><a href="#浏览器支持" class="headerlink" title="浏览器支持"></a>浏览器支持</h2><table><thead><tr><th align="center"><img src="https://img.sevth.com/website/2020/04/23/007fb2d1bca8c5a4d77bb9737be83166.png" alt="Chrome"></th><th align="center"><img src="https://img.sevth.com/website/2020/04/23/b10f92e8401be0c0cca4e4d377a6ed29.png" alt="Firefox"></th><th align="center"><img src="https://img.sevth.com/website/2020/04/23/b39699e686961cde3e357927645affc1.png" alt="Safari"></th><th align="center"><img src="https://img.sevth.com/website/2020/04/23/5adb67304aa9e3e6eea2511d20f089c2.png" alt="Opera"></th><th align="center"><img src="https://img.sevth.com/website/2020/04/23/de9a0d96608c3cd49a1221afd856028c.png" alt="Edge"></th></tr></thead><tbody><tr><td align="center">Latest ✔</td><td align="center">Latest ✔</td><td align="center">Latest ✔</td><td align="center">Latest ✔</td><td align="center">Latest ✔</td></tr></tbody></table><h2 id="快速使用"><a href="#快速使用" class="headerlink" title="快速使用"></a>快速使用</h2><p><strong>在 <code>head</code> 中添加 <code>script</code> 标签:</strong></p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><script src="https://cdn.sevth.com/website/counter_js/counter.min.js"></script></span><br></pre></td></tr></table></figure></div><h2 id="数据说明"><a href="#数据说明" class="headerlink" title="数据说明"></a>数据说明</h2><h3 id="返回数据"><a href="#返回数据" class="headerlink" title="返回数据"></a>返回数据</h3><p><strong>引入 <code>script</code> 后,将返回四个数据:</strong></p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">callback({</span><br><span class="line">site_pv:12//站点总访问量</span><br><span class="line">site_uv:4//站点访问人次</span><br><span class="line">page_pv:6//当前页面访问量</span><br><span class="line">version:1.0//版本号</span><br><span class="line">})</span><br></pre></td></tr></table></figure></div><p>其中 <code>site_pv</code> 将自动填入页面中 <code>id</code> 为 <code>counter-site-pv</code> 的容器中,<code>site_uv</code> 将自动填入页面中 <code>id</code> 为 <code>counter-site-uv</code> 的容器中,<code>page_pv</code> 将自动填入页面中 <code>id</code> 为 <code>counter-page_pv</code> 的容器中。 <code>version</code> 暂时没有其他作用。</p><h3 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h3><div class="highlight-container"><figure class=" highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><script></span><br><span class="line"> <span class="built_in">window</span>.counter_config = {</span><br><span class="line"> strict: <span class="literal">true</span><span class="comment">//启用严格uv统计模式</span></span><br><span class="line"> }</span><br><span class="line"><<span class="regexp">/script></span></span><br></pre></td></tr></table></figure></div><p>这个开关的作用就是在统计 <code>uv</code> 时更严格。统计的原理是首次访问时将写入一个检测 <code>cookie</code> ,未开启时,每过24h,旧用户将按照新用户计入 <code>uv</code> ,也就是cookie将在24h后删除,再次访问就相当于一个新用户了,开启严格模式后,用户在24h内访问一次,将刷新<code>cookie</code> 时间。按访问自然人统计。</p><p><strong>注意:该配置默认是关闭的</strong></p><h2 id="实例"><a href="#实例" class="headerlink" title="实例"></a>实例</h2><div class="highlight-container"><figure class=" highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><!DOCTYPE <span class="meta-keyword">html</span>></span></span><br><span class="line"><span class="tag"><<span class="name">html</span> <span class="attr">lang</span>=<span class="string">"en"</span>></span></span><br><span class="line"><span class="tag"><<span class="name">head</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">title</span>></span>Title<span class="tag"></<span class="name">title</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">script</span>></span></span><br><span class="line"><span class="javascript"> <span class="built_in">window</span>.counter_config = {</span></span><br><span class="line"><span class="actionscript"> strict: <span class="literal">true</span></span></span><br><span class="line"> }</span><br><span class="line"> <span class="tag"></<span class="name">script</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">script</span> <span class="attr">src</span>=<span class="string">"https://cdn.sevth.com/website/counter_js/counter.min.js"</span>></span><span class="tag"></<span class="name">script</span>></span></span><br><span class="line"><span class="tag"></<span class="name">head</span>></span></span><br><span class="line"><span class="tag"><<span class="name">body</span>></span></span><br><span class="line"><span class="tag"><<span class="name">div</span>></span></span><br><span class="line">总人数:<span class="tag"><<span class="name">span</span> <span class="attr">id</span>=<span class="string">"counter-site-uv"</span>></span>99+<span class="tag"></<span class="name">span</span>></span></span><br><span class="line"><span class="tag"><<span class="name">br</span>></span></span><br><span class="line">此页面访问量:<span class="tag"><<span class="name">span</span> <span class="attr">id</span>=<span class="string">"counter-page-pv"</span>></span>99+<span class="tag"></<span class="name">span</span>></span></span><br><span class="line"><span class="tag"><<span class="name">br</span>></span></span><br><span class="line">本站总访问量:<span class="tag"><<span class="name">span</span> <span class="attr">id</span>=<span class="string">"counter-site-pv"</span>></span>99+<span class="tag"></<span class="name">span</span>></span></span><br><span class="line"><span class="tag"></<span class="name">div</span>></span></span><br><span class="line"><span class="tag"></<span class="name">body</span>></span></span><br><span class="line"><span class="tag"></<span class="name">html</span>></span></span><br></pre></td></tr></table></figure></div><h2 id=""><a href="#" class="headerlink" title=""></a></h2><h2 id="-1"><a href="#-1" class="headerlink" title=""></a></h2><h2 id="webpack-打包"><a href="#webpack-打包" class="headerlink" title="webpack 打包"></a>webpack 打包</h2><ol><li><p>克隆仓库</p><div class="highlight-container"><figure class=" highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> https://github.com/sevth-developer/counter_js.git</span><br></pre></td></tr></table></figure></div></li><li><p>进入目录并安装依赖</p><div class="highlight-container"><figure class=" highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> ./counter_js && npm install</span><br></pre></td></tr></table></figure></div></li><li><p>打包文件</p><div class="highlight-container"><figure class=" highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run build</span><br></pre></td></tr></table></figure></div><p>打包完成后会在 <code>dist</code> 目录生成打包好的文件。</p></li></ol><h2 id="计划"><a href="#计划" class="headerlink" title="计划"></a>计划</h2><ul><li><input disabled="" type="checkbox"> <del>访问热度页面统计接口</del> </li></ul><blockquote><p>因为页面 <code>url</code> 经过<code>base64</code>编码后,字符长度超了,所以改用<code>sha1</code> 那么,就没办法做统计了。</p></blockquote><h2 id="警告"><a href="#警告" class="headerlink" title="警告"></a>警告</h2><blockquote><p>为推进互联网从 <code>http</code> 过渡到 <code>https</code> ,默认提供的加载地址仅支持 <code>https</code> 方式访问,如果有特殊需要,请自行下载文件引入。</p></blockquote><h2 id="支持"><a href="#支持" class="headerlink" title="支持"></a>支持</h2><ul><li><a href="/go/?h">Issues</a></li><li><a href="https://sevth.com">sevth的小破站</a></li><li><a href="mailto:sevthdev@gmail.com">sevthdev@gmail.com</a></li></ul>]]></content>
<summary type="html">
<blockquote>
<p>因为懒,不想写过说明,直接从 <code>github</code> 上 copy 过来了,将就着看吧,因为是使用的 <code>Dom</code> 监听事件,所以,是不支持 <code>Pjax</code> 了,再然后,有一点小小的失误,里面用了箭头函数,也就是低版本的浏览器兼容性没做,改天有空再修改一下吧。</p>
<p>关于后台程序,有空会整理出来,最后,我只是一个小菜鸟,写的并不好。</p>
</blockquote>
</summary>
<category term="develop" scheme="https://sevth.com/categories/develop/"/>
<category term="javascript" scheme="https://sevth.com/categories/develop/javascript/"/>
<category term="自制" scheme="https://sevth.com/tags/%E8%87%AA%E5%88%B6/"/>
<category term="计数器" scheme="https://sevth.com/tags/%E8%AE%A1%E6%95%B0%E5%99%A8/"/>
</entry>
<entry>
<title>如何配置hexo的deploy同时发布到GitHub和rsync</title>
<link href="https://sevth.com/technology/website/%E5%A6%82%E4%BD%95%E9%85%8D%E7%BD%AEhexo%E7%9A%84deploy%E5%90%8C%E6%97%B6%E5%8F%91%E5%B8%83%E5%88%B0GitHub%E5%92%8Crsync.html"/>
<id>https://sevth.com/technology/website/%E5%A6%82%E4%BD%95%E9%85%8D%E7%BD%AEhexo%E7%9A%84deploy%E5%90%8C%E6%97%B6%E5%8F%91%E5%B8%83%E5%88%B0GitHub%E5%92%8Crsync.html</id>
<published>2020-04-16T06:10:01.000Z</published>
<updated>2020-05-03T18:31:23.721Z</updated>
<content type="html"><![CDATA[<blockquote><p>配置 <code>deploy</code> 快速发布,免去手动上传的烦恼。</p><p>配置多个 <code>deploy</code> 同时发布,作镜像备份。</p></blockquote><a id="more"></a><h2 id="配置deploy到GitHub"><a href="#配置deploy到GitHub" class="headerlink" title="配置deploy到GitHub"></a>配置deploy到GitHub</h2><h3 id="新建一个仓库"><a href="#新建一个仓库" class="headerlink" title="新建一个仓库"></a>新建一个仓库</h3><ol><li>登录到GitHub页面,没有账号的话就注册一个。点击加号新建一个仓库</li></ol><p><img src="https://img.sevth.com/website/2020/04/16/778fc62cafe540741bbd6a504b64b3bf.png" alt="image-20200416145213738"></p><p>仓库名称按你自己喜欢填,如果你想访问的时候不带子目录的话,这里仓库名称应设置为 <code>username.github.io</code> ,将 <code>username</code> 替换成你的 <code>github</code> 用户名。然后其他保持默认,点绿色的按钮创建。</p><ol start="2"><li>将刚刚创建的 <code>仓库</code> 的 <code>HTTPS地址</code> 复制下来并保存。</li></ol><h3 id="hexo配置"><a href="#hexo配置" class="headerlink" title="hexo配置"></a>hexo配置</h3><ol start="2"><li><p>安装 <code>deploy</code> 插件</p><div class="highlight-container"><figure class=" highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-deployer-git --save</span><br></pre></td></tr></table></figure></div></li><li><p>打开 <code>hexo</code> 项目根目录,打开并编辑 <code>_config.yml</code> 文件</p><p>请直接找到的底部,填入如下几个信息,注意缩进保持一致!</p> <div class="highlight-container"><figure class=" highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">deploy:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">type:</span> <span class="string">git</span><span class="comment">#类型</span></span><br><span class="line"> <span class="attr">repo:</span> <span class="string">https://github.com/sevth-developer/sevth-developer.github.io.git</span><span class="comment">#仓库地址,即刚刚复制的那个链接</span></span><br><span class="line"> <span class="attr">branch:</span> <span class="string">master</span> <span class="comment">#默认分支,写一样就好</span></span><br><span class="line"> <span class="attr">message:</span> <span class="string">'update article'</span> <span class="comment">#默认提交信息,自己随意写</span></span><br></pre></td></tr></table></figure></div></li><li><p>输入命令 <code>hexo g -d</code> 提交一次,不出意外的话,系统会弹出提示框让你输入 <code>github</code> 的账号密码,记得点保存。如果没有提示,那么检查系统内 <code>git</code> 是否安装。(文末附windows版下载地址,其他系统请用命令行安装)</p><p>如果发布成功,命令行最后应该会显示 <code>deploy git done</code>字样。</p></li><li><p>进入<code>github</code>仓库检查是否有数据。</p></li></ol><h3 id="配置-GitHub-page"><a href="#配置-GitHub-page" class="headerlink" title="配置 GitHub page"></a>配置 GitHub page</h3><ol><li><p>进入仓库页面,点击顶栏的 <code>Settings</code> 按钮进入仓库设置。</p></li><li><p>页面往下拉找到 <code>github page</code> 选项</p><p><img src="https://img.sevth.com/website/2020/04/16/62ec272783ffb4614a1fb0e2755ef501.png" alt="image-20200416154642452"></p></li><li><p>一般配置的如果是这种域名仓库的形式,会自动打开这个配置选项。如果没有打开,手动打开一下就行了。</p><h4 id="自定义域名设置"><a href="#自定义域名设置" class="headerlink" title="自定义域名设置"></a>自定义域名设置</h4><ol><li><p>如果你有自己的域名,可以在 <code>Custom domain</code> 里面填入自己的域名。</p></li><li><p><code>github</code> 将在你的页面仓库根目录创建一个 <code>CNAME</code> 文件,你可以将这个文件下载下来,或者参照里面的内容自己写一个。</p></li><li><p>在你自己的 域名DNS提供商,创建一条<code>cname</code>记录,指向地址为 <code><user>.github.io</code> (你的仓库github page域名)</p></li><li><p>等待解析生效,即可使用自定义域名访问。</p></li></ol><h4 id="如何避免每次发布时-CNAME-文件丢失"><a href="#如何避免每次发布时-CNAME-文件丢失" class="headerlink" title="如何避免每次发布时 CNAME 文件丢失"></a>如何避免每次发布时 <code>CNAME</code> 文件丢失</h4><ol><li>将<code>CNAME</code> 放到对应主题目录下的 <code>source</code>文件夹内。</li></ol><p>这样每次<code>hexo</code>解析的时候都会将 <code>CNMAE</code> 文件带上,<code>deploy</code> 也不成问题了。</p><ol start="2"><li><p>安装 插件</p><div class="highlight-container"><figure class=" highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-generator-cname --save</span><br></pre></td></tr></table></figure></div><p>之后在 <code>_config.yml</code> 文件中 <code>Plugins</code> 添加一条记录:</p><div class="highlight-container"><figure class=" highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">Plugins:</span></span><br><span class="line"><span class="bullet">-</span> <span class="string">hexo-generator-cname</span></span><br></pre></td></tr></table></figure></div><p><strong>Tips:</strong> 记得在配置文件中设置一下网站的 <code>url</code>,否则生成的文件域名可能有误,导致无法使用自定义域名访问。 </p></li></ol></li></ol><h2 id="配置deploy到rsync"><a href="#配置deploy到rsync" class="headerlink" title="配置deploy到rsync"></a>配置deploy到rsync</h2><h3 id="服务器配置"><a href="#服务器配置" class="headerlink" title="服务器配置"></a>服务器配置</h3><ol><li><p>安装rsync服务</p><div class="highlight-container"><figure class=" highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install rsync</span><br></pre></td></tr></table></figure></div></li><li><p>编辑配置文件 (根据别人博客上的参考,hexo集成的rsync仅仅是使用了ssh底层传输)</p><div class="highlight-container"><figure class=" highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo vim /etc/rsymcd.conf</span><br></pre></td></tr></table></figure></div><p>配置文件输入如下内容:</p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">uid = nobody</span><br><span class="line">gid = nobody</span><br><span class="line">port = 873 #不会使用到这个端口号,防火墙可以屏蔽它</span><br><span class="line">use chroot = no</span><br><span class="line">max connections = 10</span><br><span class="line">pid file = /var/run/rsyncd.pid</span><br><span class="line">lock file = /var/run/rsync.lock</span><br><span class="line">log file = /var/log/rsyncd.log</span><br></pre></td></tr></table></figure></div></li><li><p>启动服务</p><div class="highlight-container"><figure class=" highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo rsync --daemon</span><br></pre></td></tr></table></figure></div></li></ol><h3 id="hexo配置-1"><a href="#hexo配置-1" class="headerlink" title="hexo配置"></a>hexo配置</h3><ol><li><p>安装集成插件</p><div class="highlight-container"><figure class=" highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-deployer-rsync --save</span><br></pre></td></tr></table></figure></div></li><li><p>编辑 <code>_config.yml</code> 配置文件,填入如下类似信息:</p><div class="highlight-container"><figure class=" highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">deploy:</span></span><br><span class="line"> <span class="attr">type:</span> <span class="string">rsync</span></span><br><span class="line"> <span class="attr">host:</span> <span class="string">服务器host</span></span><br><span class="line"> <span class="attr">user:</span> <span class="string">ssh用户名</span></span><br><span class="line"> <span class="attr">root:</span> <span class="string">你的站点根目录</span></span><br><span class="line"> <span class="attr">port:</span> <span class="number">22</span> <span class="comment">#ssh端口号</span></span><br><span class="line"> <span class="attr">delete:</span> <span class="literal">true</span><span class="comment">#发布时是否删除旧文件</span></span><br><span class="line"> <span class="attr">verbose:</span> <span class="literal">true</span><span class="comment">#发布时显示详细的信息</span></span><br><span class="line"> <span class="attr">ignore_errors:</span> <span class="literal">false</span><span class="comment">#发布时忽略错误</span></span><br></pre></td></tr></table></figure></div></li><li><p>测试一下,使用 <code>hexo d</code> 看看是否能够发布成功。</p></li></ol><h3 id="使用SSH公钥,免输入密码"><a href="#使用SSH公钥,免输入密码" class="headerlink" title="使用SSH公钥,免输入密码"></a>使用SSH公钥,免输入密码</h3><ol><li><p>服务器配置秘钥连接 <code>SSH</code> 参考 <a href="#参考阅读">参考阅读</a></p></li><li><p>将能够正确连接 <code>SSH</code> 的秘钥写入系统默认配置中。默认系统秘钥文件地址在 <code>~/.ssh/id_rsa</code></p><p>你可以手动复制秘钥内容至该文件内,或者使用如下方式:</p><div class="highlight-container"><figure class=" highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cat /path/to/private_rsa > ~/.ssh/id_rsa<span class="comment">#将前面修改为你自己的秘钥文件保存地址,该操作将覆盖id_rsa文件内容,如果你在此步骤之前已经存在该文件,请注意备份保存</span></span><br><span class="line">chmod go-rwx ~/.ssh/id_rsa<span class="comment">#设置权限</span></span><br></pre></td></tr></table></figure></div></li><li><p>好了,全部配置完成后,你可以试验一下看看是否正常。</p></li></ol><h4 id="修改-hexo-的-deploy插件,自定义秘钥文件位置"><a href="#修改-hexo-的-deploy插件,自定义秘钥文件位置" class="headerlink" title="修改 hexo 的 deploy插件,自定义秘钥文件位置"></a>修改 <code>hexo</code> 的 <code>deploy</code>插件,自定义秘钥文件位置</h4><ol><li><p>进入 <code>hexo</code> 项目根目录,找到 <code>deployer.js</code> 文件 (文件位于 <code>node_modules/hexo-deployer-rsync/lib/deployer.js</code>)</p></li><li><p>修改如下:</p><div class="highlight-container"><figure class=" highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">... 省略其他代码</span><br><span class="line"><span class="keyword">if</span> (!<span class="built_in">Object</span>.prototype.hasOwnProperty.call(args, <span class="string">'delete'</span>)) args.delete = <span class="literal">true</span>;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="built_in">Object</span>.prototype.hasOwnProperty.call(args, <span class="string">'verbose'</span>)) args.verbose = <span class="literal">true</span>;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="built_in">Object</span>.prototype.hasOwnProperty.call(args, <span class="string">'ignore_errors'</span>)) args.ignore_errors = <span class="literal">false</span>;</span><br><span class="line"> <span class="keyword">if</span> (!<span class="built_in">Object</span>.prototype.hasOwnProperty.call(args, <span class="string">'key'</span>)) args.key = <span class="literal">false</span>;<span class="comment">//加入此条代码</span></span><br><span class="line"></span><br><span class="line"> ... 省略一段代码</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (args.port && args.port > <span class="number">0</span> && args.port < <span class="number">65536</span>) {</span><br><span class="line"> params.splice(params.length - <span class="number">2</span>, <span class="number">0</span>, <span class="string">'-e'</span>);</span><br><span class="line"> <span class="keyword">if</span> (args.key) {<span class="comment">//添加的代码</span></span><br><span class="line"> params.splice(params.length - <span class="number">2</span>, <span class="number">0</span>, <span class="string">`ssh -p <span class="subst">${args.port}</span> -i <span class="subst">${args.key}</span>`</span>);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> params.splice(params.length - <span class="number">2</span>, <span class="number">0</span>, <span class="string">'ssh -p '</span> + args.port);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">... 省略之后代码</span><br></pre></td></tr></table></figure></div></li><li><p>在项目的配置文件<code>deploy</code> 添加一项 <code>key</code> 后面填写私钥地址,如下:</p><div class="highlight-container"><figure class=" highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">deploy:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">type:</span> <span class="string">rsync</span></span><br><span class="line"> <span class="attr">host:</span> <span class="string">ip</span></span><br><span class="line"> <span class="attr">user:</span> <span class="string">user</span></span><br><span class="line"> <span class="attr">root:</span> <span class="string">path</span></span><br><span class="line"> <span class="attr">port:</span> <span class="number">22</span></span><br><span class="line"> <span class="attr">delete:</span> <span class="literal">true</span><span class="string">/false</span></span><br><span class="line"> <span class="attr">verbose:</span> <span class="literal">true</span><span class="string">/false</span></span><br><span class="line"> <span class="attr">ignore_errors:</span> <span class="literal">true</span><span class="string">/false</span></span><br><span class="line"> <span class="attr">key:</span> <span class="string">~/.ssh/web_rsa</span></span><br></pre></td></tr></table></figure></div></li></ol><blockquote><p>Tips: 生成秘钥对的时候,不要输入私钥密码。可能会直接失败或者每次都要求输入密码。</p></blockquote><h2 id="配置同时发布"><a href="#配置同时发布" class="headerlink" title="配置同时发布"></a>配置同时发布</h2><p>编辑 <code>_config.yml</code> 文件,按照如下格式填写:</p><div class="highlight-container"><figure class=" highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">deploy:</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">type:</span> <span class="string">rsync</span></span><br><span class="line"> <span class="attr">host:</span> <span class="string">ip</span></span><br><span class="line"> <span class="attr">user:</span> <span class="string">用户名</span></span><br><span class="line"> <span class="attr">root:</span> <span class="string">站点根目录</span></span><br><span class="line"> <span class="attr">port:</span> <span class="number">22</span></span><br><span class="line"> <span class="attr">delete:</span> <span class="literal">true</span></span><br><span class="line"> <span class="attr">verbose:</span> <span class="literal">true</span></span><br><span class="line"> <span class="attr">ignore_errors:</span> <span class="literal">false</span></span><br><span class="line"></span><br><span class="line"><span class="bullet">-</span> <span class="attr">type:</span> <span class="string">git</span></span><br><span class="line"> <span class="attr">repo:</span> <span class="string">你的仓库地址</span></span><br><span class="line"> <span class="attr">branch:</span> <span class="string">master</span></span><br><span class="line"> <span class="attr">message:</span> <span class="string">'update article'</span></span><br></pre></td></tr></table></figure></div><p>测试一下。</p><p><img src="https://img.sevth.com/website/2020/04/16/3b01c439a14e88a77a980f3a2702071f.png" alt="image-20200416165646239"></p><h2 id="附件下载"><a href="#附件下载" class="headerlink" title="附件下载"></a>附件下载</h2><ol><li><a href="https://file.sevth.com/website/2020/04/16/bf86c2ab0d01da19e57817d3fb630317.zip">Git-2.26.1-64-bit</a></li></ol><h2 id="参考阅读"><a href="#参考阅读" class="headerlink" title="参考阅读"></a>参考阅读</h2><ol><li><a href="/go/?8">Github Page 自定义域名官方说明</a></li><li><a href="/go/?9">将Hexo部署到 GitHub Pages</a></li><li><a href="/go/?a">Hexo 一键部署</a></li><li><a href="/go/?b">hexo使用rsync部署发布</a></li><li><a href="/go/?c">设置 SSH 通过密钥登录</a></li></ol>]]></content>
<summary type="html">
<blockquote>
<p>配置 <code>deploy</code> 快速发布,免去手动上传的烦恼。</p>
<p>配置多个 <code>deploy</code> 同时发布,作镜像备份。</p>
</blockquote>
</summary>
<category term="technology" scheme="https://sevth.com/categories/technology/"/>
<category term="website" scheme="https://sevth.com/categories/technology/website/"/>
<category term="hexo" scheme="https://sevth.com/tags/hexo/"/>
<category term="deploy" scheme="https://sevth.com/tags/deploy/"/>
<category term="rsync" scheme="https://sevth.com/tags/rsync/"/>
</entry>
<entry>
<title>如何优雅地用shell快速创作并发布</title>
<link href="https://sevth.com/technology/shell/%E5%A6%82%E4%BD%95%E4%BC%98%E9%9B%85%E5%9C%B0%E7%94%A8shell%E5%BF%AB%E9%80%9F%E5%88%9B%E4%BD%9C%E5%B9%B6%E5%8F%91%E5%B8%83.html"/>
<id>https://sevth.com/technology/shell/%E5%A6%82%E4%BD%95%E4%BC%98%E9%9B%85%E5%9C%B0%E7%94%A8shell%E5%BF%AB%E9%80%9F%E5%88%9B%E4%BD%9C%E5%B9%B6%E5%8F%91%E5%B8%83.html</id>
<published>2020-04-15T19:54:40.000Z</published>
<updated>2020-05-03T18:31:58.489Z</updated>
<content type="html"><![CDATA[<blockquote><p>他来了他来了,他带着新造的东西过来了。(每天熬夜肝代码是不好的行为习惯,我决定,明天一定要早点睡!!!)</p><p>今天写的东西是一个<code>shell</code>,其实就是<code>hexo</code> 的一个辅助工具,之前每次写文章都要打开终端,然后 <code>cd</code>到路径再 <code>hexo new post</code>,然后又要从<code>finder</code> 打开一层一层的文件夹用<code>typora</code> 打开后才能开始写作。发布的时候,又要重复前面的两步,真的是烦得很,虽然官方给了<code>cli</code> 工具已经够方便了,<code>But</code> 我就是喜欢偷懒。</p></blockquote><a id="more"></a><h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><ul><li><p>优雅,快速,无残留</p><p>虽然是用我一个晚上的时间速成写的,但是功能还是很ok的,目前只在我的<code>mac</code>实验了正常工作,对于其他 <code>linux</code> 并未作测试,当然, <code>windows</code>更加不能用。如果有需求的话,再考虑叭。</p></li><li><p>可拓展</p><p>扩展是基于官方的 <code>cli</code> 工具,也就是功能可以随着官方工具而扩展,但是目前只加入了我认为必要的一些功能,其他的正常使用时都鸡肋(我使用的时间觉得鸡肋)的功能肯定是没有的。</p></li><li><p>命令简单</p><p>没有花里胡哨的东西,你完全可以打简写快速执行一些操作,比如官方中有的 <code>hexo s</code> 也许可以加入组合功能?比如 <code>hexo g -d</code>。</p></li></ul><h2 id="功能"><a href="#功能" class="headerlink" title="功能"></a>功能</h2><p><img src="https://img.sevth.com/website/2020/04/16/0c8a117d7dbdf8e0334e2531cddfb712.png" alt="image-20200416041601166"></p><p>看图,使用<code>h</code> 或者 <code>help</code> 参数可以查看,目前基本支持的就这几个。功能与官方一致,说到这,有人就要问了,既然功能一致,那它有啥用?</p><h3 id="快速创建新文章"><a href="#快速创建新文章" class="headerlink" title="快速创建新文章"></a>快速创建新文章</h3><p>在命令行里直接回车就行了,或者配置好后,在桌面直接双击运行。运行后它长这样:</p><p><img src="https://img.sevth.com/website/2020/04/16/27e5c8e4506c4d5b41339897a8746d5f.png" alt="image-20200416042034744"></p><p>这里直接新建文章操作,实际上你可能只需要输入一个文章标题,其他的<code>shell</code> 会自动配置好。</p><h3 id="信息确认"><a href="#信息确认" class="headerlink" title="信息确认"></a>信息确认</h3><p>为了不让你多输几个字,所以默认只有数据回显,并不进行数据确认。</p><p>如下:</p><p><img src="https://img.sevth.com/website/2020/04/16/48fe110b7a18f71196aee6243281c6b8.png" alt="image-20200416042913300"></p><h3 id="快速写作"><a href="#快速写作" class="headerlink" title="快速写作"></a>快速写作</h3><p>基本上新建文章完成了之后会自动用 <code>typora</code> 打开。当然,如果你用其他的软件写作,那么它打开的就是你写作使用的默认软件了。</p><p><img src="https://img.sevth.com/website/2020/04/16/3b697eeca18a7976f32da0ff4ca2bb99.png" alt="image-20200416043257500"></p><h3 id="等待发布"><a href="#等待发布" class="headerlink" title="等待发布"></a>等待发布</h3><p>是的,它会在后台静静的等待你写作完成,然后问你要不要直接发布出去文章。前提是你已经配置好了 <code>Hexo</code> 的 <code>deploy</code> 配置。(预留坑位,配置hexo同时发布到git 和 rsync)</p><p><img src="https://img.sevth.com/website/2020/04/16/eeb063562ee8fde898b7593d826fdea0.png" alt="image-20200416040519480"></p><p><img src="https://img.sevth.com/website/2020/04/16/5ef67006bfeeea268add9d2e4f5242bd.png" alt="image-20200416044235017"></p><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><ul><li>下载脚本</li></ul><p>github </p><div class="highlight-container"><figure class=" highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -o hexo https://raw.githubusercontent.com/sevth-developer/tools/master/shell/hexo.command && chmod +x ./hexo</span><br></pre></td></tr></table></figure></div><p>本站</p><div class="highlight-container"><figure class=" highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl - o hexo https://cdn.sevth.com/website/2020/04/16/282d18cf0e254da3d7c389b7c5854886.command && chmod +x ./hexo</span><br></pre></td></tr></table></figure></div><ul><li>编辑默认 <code>hexo</code> 文件夹设置。</li></ul><div class="highlight-container"><figure class=" highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sed -i <span class="string">""</span> <span class="string">"s:/Users/sevth/workspace/sevth:/Path/to/you/folder:g"</span> ./hexo</span><br></pre></td></tr></table></figure></div><p>这里替换时,将 <code>/Path/to/you/folder</code> 换成你的博客文件夹根目录,尾部不带 <code>/</code> ,然后执行上面这条命令即可。或者你也可以使用文本编辑器打开,手动修改 <code>base_path=</code>为你的文件夹地址。</p><ul><li>或者你也可以手动下载脚本文件,如下,请右键另存为。</li></ul><h2 id="附件下载:"><a href="#附件下载:" class="headerlink" title="附件下载:"></a>附件下载:</h2><p><a href="https://file.sevth.com/website/2020/04/16/282d18cf0e254da3d7c389b7c5854886.command">hexo</a></p><h2 id="反馈"><a href="#反馈" class="headerlink" title="反馈"></a>反馈</h2><ul><li>直接在本文下面留言</li><li>在 <code>github</code> 上提交<a href="/go/?e">issues</a></li></ul>]]></content>
<summary type="html">
<blockquote>
<p>他来了他来了,他带着新造的东西过来了。(每天熬夜肝代码是不好的行为习惯,我决定,明天一定要早点睡!!!)</p>
<p>今天写的东西是一个<code>shell</code>,其实就是<code>hexo</code> 的一个辅助工具,之前每次写文章都要打开终端,然后 <code>cd</code>到路径再 <code>hexo new post</code>,然后又要从<code>finder</code> 打开一层一层的文件夹用<code>typora</code> 打开后才能开始写作。发布的时候,又要重复前面的两步,真的是烦得很,虽然官方给了<code>cli</code> 工具已经够方便了,<code>But</code> 我就是喜欢偷懒。</p>
</blockquote>
</summary>
<category term="technology" scheme="https://sevth.com/categories/technology/"/>
<category term="shell" scheme="https://sevth.com/categories/technology/shell/"/>
<category term="hexo" scheme="https://sevth.com/tags/hexo/"/>
<category term="shell" scheme="https://sevth.com/tags/shell/"/>
</entry>
<entry>
<title>网站运行时间纠错(Date的不一样用法)</title>
<link href="https://sevth.com/technology/javascript/%E7%BD%91%E7%AB%99%E8%BF%90%E8%A1%8C%E6%97%B6%E9%97%B4%E7%BA%A0%E9%94%99(Date%E7%9A%84%E4%B8%8D%E4%B8%80%E6%A0%B7%E7%94%A8%E6%B3%95).html"/>
<id>https://sevth.com/technology/javascript/%E7%BD%91%E7%AB%99%E8%BF%90%E8%A1%8C%E6%97%B6%E9%97%B4%E7%BA%A0%E9%94%99(Date%E7%9A%84%E4%B8%8D%E4%B8%80%E6%A0%B7%E7%94%A8%E6%B3%95).html</id>
<published>2020-04-15T05:26:56.000Z</published>
<updated>2020-04-28T12:43:55.256Z</updated>
<content type="html"><![CDATA[<blockquote><p>为了使网站引用的js代码更加规范,在对文件的整理过程中,发现了一个小小的 <code>Bug</code> ,网站底部的运行时间在分钟上居然差了几分钟,本着严谨的态度,开始了排错。</p></blockquote><a id="more"></a><h2 id="问题发现"><a href="#问题发现" class="headerlink" title="问题发现"></a>问题发现</h2><p><strong>网站运行时间</strong></p><p><img src="https://img.sevth.com/website/2020/04/15/ff7db44bfc35929d8ac5a1ee3bcc2fd0.png" alt="image-20200415132801070"></p><p><strong>本地时间</strong></p><p><img src="https://img.sevth.com/website/2020/04/15/f31a35e58bbd9b5ba6023607553845a3.png" alt="image-20200415132829840"></p><p>因为采用的开始计数时间是整点,那么计算的运行时间应该也是跟我们的本地时间相同的时间点。但是实际上相差了13分钟。</p><h2 id="排错"><a href="#排错" class="headerlink" title="排错"></a>排错</h2><h3 id="定位到问题点"><a href="#定位到问题点" class="headerlink" title="定位到问题点"></a>定位到问题点</h3><p><kbd>F12</kbd> 打开浏览器的控制台,使用鼠标工具直接选中运行时间一行,显示为如下:</p><div class="highlight-container"><figure class=" highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span></span><br><span class="line"><script type=<span class="string">"text/javascript"</span> src=<span class="string">"/js/statistics.js"</span>><<span class="regexp">/script><script>var now = new Date();setInterval("createTime('2020/</span><span class="number">04</span>/<span class="number">08</span> <span class="number">00</span>:<span class="number">00</span>:<span class="number">00</span><span class="string">')", 250,"");</script></span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"><span id="statistic-times">❤️本站自<span><strong> 2020.04.08</strong><span> 已运行 <strong>7</strong> 天 <strong>13</strong> 小时 <strong>34</strong> 分 <strong>48</strong> 秒!❤️</span></span></span></span></span><br><span class="line"><span class="string"><br></span></span><br><span class="line"><span class="string"></span></span></span><br></pre></td></tr></table></figure></div><p>主要分为两部分,上部分 <code>script</code> 使用定时器不停地调用函数,下面部分是 <code>id</code> 为 <code>statistic-times</code> 的文本标签。上面的脚本将数据插入到下面的文本标签中。</p><p>接下来,打开引入的 <code>js</code> 文件看一看。</p><div class="highlight-container"><figure class=" highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createTime</span>(<span class="params">time</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> n = <span class="keyword">new</span> <span class="built_in">Date</span>(time);</span><br><span class="line"> now.setTime(now.getTime() + <span class="number">250</span>),</span><br><span class="line"> days = (now - n) / <span class="number">1e3</span> / <span class="number">60</span> / <span class="number">60</span> / <span class="number">24</span>,</span><br><span class="line"> dnum = <span class="built_in">Math</span>.floor(days),</span><br><span class="line"> hours = (now - n) / <span class="number">1e3</span> / <span class="number">60</span> / <span class="number">60</span> - <span class="number">24</span> * dnum,</span><br><span class="line"> hnum = <span class="built_in">Math</span>.floor(hours),</span><br><span class="line"> <span class="number">1</span> == <span class="built_in">String</span>(hnum).length && (hnum = <span class="string">"0"</span> + hnum),</span><br><span class="line"> minutes = (now - n) / <span class="number">1e3</span> / <span class="number">60</span> - <span class="number">1440</span> * dnum - <span class="number">60</span> * hnum,</span><br><span class="line"> mnum = <span class="built_in">Math</span>.floor(minutes),</span><br><span class="line"> <span class="number">1</span> == <span class="built_in">String</span>(mnum).length && (mnum = <span class="string">"0"</span> + mnum),</span><br><span class="line"> seconds = (now - n) / <span class="number">1e3</span> - <span class="number">86400</span> * dnum - <span class="number">3600</span> * hnum - <span class="number">60</span> * mnum,</span><br><span class="line"> snum = <span class="built_in">Math</span>.round(seconds),</span><br><span class="line"> <span class="number">1</span> == <span class="built_in">String</span>(snum).length && (snum = <span class="string">"0"</span> + snum),</span><br><span class="line"> <span class="built_in">document</span>.getElementById(<span class="string">"statistic-times"</span>).innerHTML = <span class="string">"❤️本站自<span><strong> "</span>+time.split(<span class="string">" "</span>)[<span class="number">0</span>].replace(<span class="regexp">/\//g</span>,<span class="string">"."</span>)+<span class="string">"</strong><span> 已运行 <strong>"</span> + dnum + <span class="string">"</strong> 天 <strong>"</span> + hnum + <span class="string">"</strong> 小时 <strong>"</span> + mnum + <span class="string">"</strong> 分 <strong>"</span> + snum + <span class="string">"</strong> 秒!❤️"</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><p>貌似代码写的都没啥问题,但是有点杂乱。并且发现一个小问题。 <code>now</code> 给的值是一个全局常量,并没有重新获取。然后发现产生的原因居然是,浏览器窗口被缩小之后,网页上的<code>js</code> 自然而然不再运行。</p><h2 id="解决"><a href="#解决" class="headerlink" title="解决"></a>解决</h2><p>最简单的办法就是在函数运行的时候,每次都重新取 <code>now</code> 值。</p><div class="highlight-container"><figure class=" highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">createTime</span>(<span class="params">time</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> n = <span class="keyword">new</span> <span class="built_in">Date</span>(time);</span><br><span class="line"> <span class="keyword">let</span> now = <span class="keyword">new</span> <span class="built_in">Date</span>();<span class="comment">//添加此条到函数内部</span></span><br><span class="line"> now.setTime(now.getTime() + <span class="number">250</span>),</span><br><span class="line"> ...以下省略</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><h2 id="优化写法"><a href="#优化写法" class="headerlink" title="优化写法"></a>优化写法</h2><p>感兴趣的话,研究一下 <code>Data</code> 的用法,我们可以将函数简化如下:</p><div class="highlight-container"><figure class=" highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">SiteTimeFrom</span>(<span class="params">time</span>) </span>{</span><br><span class="line"> <span class="keyword">let</span> diffTime = <span class="keyword">new</span> <span class="built_in">Date</span>( <span class="keyword">new</span> <span class="built_in">Date</span>() - <span class="keyword">new</span> <span class="built_in">Date</span>(time));</span><br><span class="line"> <span class="keyword">let</span> day = <span class="built_in">Math</span>.floor(diffTime / <span class="number">24</span> /<span class="number">3.6e6</span>);</span><br><span class="line"> <span class="built_in">document</span>.getElementById(<span class="string">"statistic-times"</span>).innerHTML = <span class="string">"❤️本站自<span><strong> "</span>+time.split(<span class="string">" "</span>)[<span class="number">0</span>].replace(<span class="regexp">/\//g</span>,<span class="string">"."</span>)+<span class="string">"</strong><span> 已运行 <strong>"</span> + day + <span class="string">"</strong> 天 <strong>"</span> + diffTime.getUTCHours() + <span class="string">"</strong> 小时 <strong>"</span> + diffTime.getUTCMinutes() + <span class="string">"</strong> 分 <strong>"</span> + diffTime.getUTCSeconds() + <span class="string">"</strong> 秒!❤️"</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><h3 id="tips"><a href="#tips" class="headerlink" title="tips"></a>tips</h3><p>使用 <code>Date(dateTime)</code> 之类的写法,相当于 <code>Date().parse(dataTime)</code>。那么当我们将差值传进去构造一个 <code>Date</code> 对象时,它的时间就是从 <code>1970/01/01 00:00:00</code> 开始计算的。那么一天内的时间我们可以通过方法从该对象中获取,而天数计算仍然使用时间差算法,也就是 <code>timestamp</code> 除以 一天的 <code>24 * 3.6e6</code> 秒。</p><p><strong><em>注意:</em></strong> 获取小时的时候,应该用 <code>UTC</code> 的小时,不然 <code>Date</code> 对象会自动转换为本地时间,那么取值的时候就会相差8h。而分钟和秒都是一样的,使不使用 <code>UTC</code> 时间都行。<code>(getMinutes()、 getSeconds())</code></p>]]></content>
<summary type="html">
<blockquote>
<p>为了使网站引用的js代码更加规范,在对文件的整理过程中,发现了一个小小的 <code>Bug</code> ,网站底部的运行时间在分钟上居然差了几分钟,本着严谨的态度,开始了排错。</p>
</blockquote>
</summary>
<category term="technology" scheme="https://sevth.com/categories/technology/"/>
<category term="javascript" scheme="https://sevth.com/categories/technology/javascript/"/>
<category term="javascript" scheme="https://sevth.com/tags/javascript/"/>
</entry>
<entry>
<title>如何使你的手机chrome浏览器自适应网站的夜间模式</title>
<link href="https://sevth.com/technology/website/%E5%A6%82%E4%BD%95%E4%BD%BF%E4%BD%A0%E7%9A%84%E6%89%8B%E6%9C%BAchrome%E6%B5%8F%E8%A7%88%E5%99%A8%E8%87%AA%E9%80%82%E5%BA%94%E7%BD%91%E7%AB%99%E7%9A%84%E5%A4%9C%E9%97%B4%E6%A8%A1%E5%BC%8F.html"/>
<id>https://sevth.com/technology/website/%E5%A6%82%E4%BD%95%E4%BD%BF%E4%BD%A0%E7%9A%84%E6%89%8B%E6%9C%BAchrome%E6%B5%8F%E8%A7%88%E5%99%A8%E8%87%AA%E9%80%82%E5%BA%94%E7%BD%91%E7%AB%99%E7%9A%84%E5%A4%9C%E9%97%B4%E6%A8%A1%E5%BC%8F.html</id>
<published>2020-04-14T18:06:36.000Z</published>
<updated>2020-04-28T12:43:32.951Z</updated>
<content type="html"><![CDATA[<h2 id="啰里啰嗦"><a href="#啰里啰嗦" class="headerlink" title="啰里啰嗦"></a>啰里啰嗦</h2><blockquote><p>Mac 电脑系列在比较早(10.14 mojave)的时候就有了 <code>深色模式</code> ,这个模式在晚上使用的感觉是更加棒,以至于我现在任何时候都开着这个模式使用。当然,这个模式确实能够节能一些,但是并没有护眼的效果。所以,它仅仅是让你的眼睛看着舒服一些。当然,黑色的界面也显得很酷😎。</p></blockquote><a id="more"></a><h2 id="一些废话"><a href="#一些废话" class="headerlink" title="一些废话"></a>一些废话</h2><p>网站加入了夜间模式,当设置的时间到了之后,就会自动切换到夜间模式,使夜间浏览起来更舒适,那么,怎么让浏览器被动的跟着变黑呢?</p><h2 id="关键位置"><a href="#关键位置" class="headerlink" title="关键位置"></a>关键位置</h2><p>网站页面的 <code>head</code> 部分就是用来描述页面和加载一些脚本文件的。自从 <code>chrome</code> 39开始,<code>chrome</code> 浏览器支持网页中名为 <code>theme-color</code> 的 <code>meta</code> 标签。只要设置这一个标签,浏览器会随着设置的值改变标签栏的颜色。</p><p>类似的代码如下:</p><div class="highlight-container"><figure class=" highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">meta</span> <span class="attr">name</span>=<span class="string">"theme-color"</span> <span class="attr">content</span>=<span class="string">"#FFFFFF"</span>></span></span><br></pre></td></tr></table></figure></div><h2 id="修改"><a href="#修改" class="headerlink" title="修改"></a>修改</h2><p>定位到我们网站的切换深夜模式的代码:</p><div class="highlight-container"><figure class=" highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">applyNight</span>(<span class="params">value</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (value == <span class="string">'true'</span>) {</span><br><span class="line"> <span class="built_in">document</span>.body.className += <span class="string">' night'</span>;</span><br><span class="line"> nightIcon.className = nightIcon.className.replace(<span class="regexp">/ fa-moon/g</span>, <span class="string">''</span>) + <span class="string">' fa-sun'</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="built_in">document</span>.body.className = <span class="built_in">document</span>.body.className.replace(<span class="regexp">/ night/g</span>, <span class="string">''</span>)</span><br><span class="line"> nightIcon.className = nightIcon.className.replace(<span class="regexp">/ fa-sun/g</span>, <span class="string">''</span>) + <span class="string">' fa-moon'</span></span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"><span class="comment">//省略一堆代码,此处仅实例,单独使用无效</span></span><br></pre></td></tr></table></figure></div><p>核心代码就是判断传入值是否为真,这里传入的值是夜间模式的判断。因为 夜间模式的实现主要是依靠 <code>css</code> 的 <code>!important</code> 语法覆盖实现的,所以这里就只需要添加 <code>.night</code> 就可以了。</p><p>那么我们综合分析一下,这个应该插入到 <code>if</code> 循环中去。</p><p>原生 <code>js</code> 操作如下:</p><div class="highlight-container"><figure class=" highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> c = <span class="built_in">document</span>.getElementsByName(<span class="string">'theme-color'</span>);</span><br><span class="line">c[<span class="number">0</span>].content = <span class="string">"#151313"</span>;</span><br></pre></td></tr></table></figure></div><p><code>getElementsByName</code> 方法返回的是一个数组,这里直接取下标 0 ,完整示例如下:</p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">var nightIcon = document.getElementById('night-icon');</span><br><span class="line">var chrome_color = document.getElementsByName('theme-color');</span><br><span class="line">function applyNight(value) {</span><br><span class="line"> if (value == 'true') {</span><br><span class="line"> document.body.className += ' night';</span><br><span class="line"> nightIcon.className = nightIcon.className.replace(/ fa-moon/g, '') + ' fa-sun';</span><br><span class="line"> chrome_color[0].content = "#151313"; //切换夜间模式 设置颜色值</span><br><span class="line"> } else {</span><br><span class="line"> document.body.className = document.body.className.replace(/ night/g, '')</span><br><span class="line"> nightIcon.className = nightIcon.className.replace(/ fa-sun/g, '') + ' fa-moon';</span><br><span class="line"> chrome_color[0].content = "#FFFFFF";//切换回日间模式 设置颜色值</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><h2 id="其他受支持的一些属性"><a href="#其他受支持的一些属性" class="headerlink" title="其他受支持的一些属性"></a>其他受支持的一些属性</h2><div class="highlight-container"><figure class=" highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">// windows phone</span><br><span class="line"><span class="tag"><<span class="name">meta</span> <span class="attr">name</span>=<span class="string">"msapplication-navbutton-color"</span> <span class="attr">content</span>=<span class="string">"#FFF"</span>></span></span><br><span class="line">// ios safari</span><br><span class="line"><span class="tag"><<span class="name">meta</span> <span class="attr">name</span>=<span class="string">"apple-mobile-web-app-status-bar-style"</span> <span class="attr">content</span>=<span class="string">"#FFF"</span>></span></span><br><span class="line"></span><br><span class="line">//浏览器卡片页图标</span><br><span class="line"><span class="tag"><<span class="name">link</span> <span class="attr">rel</span>=<span class="string">"apple-touch-icon"</span> <span class="attr">href</span>=<span class="string">"/img/favicon.png"</span>/></span> //apple</span><br><span class="line"><span class="tag"><<span class="name">link</span> <span class="attr">rel</span>=<span class="string">"icon"</span> <span class="attr">sizes</span>=<span class="string">"192x192"</span> <span class="attr">href</span>=<span class="string">"/img/favicon.png"</span>/></span> //android</span><br></pre></td></tr></table></figure></div><p><strong>待后面整理完成了相关的文件,会将代码上传到<code>GitHub</code>上。</strong></p><h2 id="参考阅读"><a href="#参考阅读" class="headerlink" title="参考阅读"></a>参考阅读</h2><ul><li><a href="/go/?d">https://developers.google.com/web/updates/2014/11/Support-for-theme-color-in-Chrome-39-for-Android</a></li></ul>]]></content>
<summary type="html">
<h2 id="啰里啰嗦"><a href="#啰里啰嗦" class="headerlink" title="啰里啰嗦"></a>啰里啰嗦</h2><blockquote>
<p>Mac 电脑系列在比较早(10.14 mojave)的时候就有了 <code>深色模式</code> ,这个模式在晚上使用的感觉是更加棒,以至于我现在任何时候都开着这个模式使用。当然,这个模式确实能够节能一些,但是并没有护眼的效果。所以,它仅仅是让你的眼睛看着舒服一些。当然,黑色的界面也显得很酷😎。</p>
</blockquote>
</summary>
<category term="technology" scheme="https://sevth.com/categories/technology/"/>
<category term="website" scheme="https://sevth.com/categories/technology/website/"/>
<category term="dark mode" scheme="https://sevth.com/tags/dark-mode/"/>
<category term="website" scheme="https://sevth.com/tags/website/"/>
<category term="html" scheme="https://sevth.com/tags/html/"/>
</entry>
<entry>
<title>Mac小技巧:更新失败怎么当做什么都没有发生过</title>
<link href="https://sevth.com/Mac/tips/Mac%E5%B0%8F%E6%8A%80%E5%B7%A7%EF%BC%9A%E6%9B%B4%E6%96%B0%E5%A4%B1%E8%B4%A5%E6%80%8E%E4%B9%88%E5%BD%93%E5%81%9A%E4%BB%80%E4%B9%88%E9%83%BD%E6%B2%A1%E6%9C%89%E5%8F%91%E7%94%9F%E8%BF%87.html"/>
<id>https://sevth.com/Mac/tips/Mac%E5%B0%8F%E6%8A%80%E5%B7%A7%EF%BC%9A%E6%9B%B4%E6%96%B0%E5%A4%B1%E8%B4%A5%E6%80%8E%E4%B9%88%E5%BD%93%E5%81%9A%E4%BB%80%E4%B9%88%E9%83%BD%E6%B2%A1%E6%9C%89%E5%8F%91%E7%94%9F%E8%BF%87.html</id>
<published>2020-04-14T06:53:51.000Z</published>
<updated>2020-04-26T10:37:19.903Z</updated>
<content type="html"><![CDATA[<blockquote><p>这篇文章仅针对于黑苹果用户,如果是白苹果,应该也是可以这么做的,本文仅提供参考,给一台非<code>mac</code>机器装上<code>Mac OS</code>系统称为黑苹果(hackintosh),虽然这违反了苹果公司的最终用户许可协议(<a href="/go/?f">EULA</a>,但是这是一种极客体验的方式。我不推荐这么做,并且最终选择权在你手中。</p><p>系统更新失败怎么办?启动界面多了一个烦人的图标?</p></blockquote><a id="more"></a><h2 id="起因"><a href="#起因" class="headerlink" title="起因"></a>起因</h2><p>最近 <code>Mac</code> 推送了<a href="/go/?g">2020-002 更新</a> 手贱点了更新按钮,然后开机的时候一直卡着进度条没动,只好重启电脑重新进系统,然而这个启动选项可是一直都在,真是讨厌😠。</p><h2 id="参考办法"><a href="#参考办法" class="headerlink" title="参考办法"></a>参考办法</h2><h3 id="使用软件修改-config-plist-,将启动项隐藏。(仅限黑苹果用户)-不推荐"><a href="#使用软件修改-config-plist-,将启动项隐藏。(仅限黑苹果用户)-不推荐" class="headerlink" title="使用软件修改 config.plist ,将启动项隐藏。(仅限黑苹果用户)(不推荐)"></a>使用软件修改 <code>config.plist</code> ,将启动项隐藏。(仅限黑苹果用户)(不推荐)</h3><ol><li><p>使用 <code>clover configurator</code> 软件,挂载分区</p><p><img src="https://img.sevth.com/website/2020/04/14/825bd574da168e172c831a37f90f6a63.png" alt="image-20200414153101431"></p></li><li><p><strong>修改 <code>引导界面</code> 设置</strong></p><p><img src="https://img.sevth.com/website/2020/04/14/6b63c7f9dcb82b2ca00c239d1a23881b.png" alt="image-20200414153333742"></p><p>添加一条记录,参照值为你在开机时看到的选项名称。</p></li><li><p>保存设置。</p></li></ol><h3 id="进入系统,删除更新安装文件(白苹果适用)(推荐)"><a href="#进入系统,删除更新安装文件(白苹果适用)(推荐)" class="headerlink" title="进入系统,删除更新安装文件(白苹果适用)(推荐)"></a>进入系统,删除更新安装文件(白苹果适用)(推荐)</h3><ol><li><p>打开终端软件(打开方法见:<a href="/Mac/tips/Mac小技巧:去掉更新设置小红点.html">点我查看</a>)</p></li><li><p>输入如下指令删除 <code>更新文件夹</code></p><div class="highlight-container"><figure class=" highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo rm -r /<span class="string">"Macos install data"</span></span><br></pre></td></tr></table></figure></div><p>中间需要输入密码,密码不显示。</p><p>如果提示文件夹不存在,就使用 <code>ls /</code> 指令查看一下根目录,有一个类似上面名称的文件夹,再输入上面的指令,替换成正确的文件夹名称执行即可。</p></li></ol><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><ul><li>无论白苹果还是黑苹果,在更新之前都应该使用时间机器做好备份,避免意外情况发生导致数据丢失!</li></ul><h3 id="可能用到的软件"><a href="#可能用到的软件" class="headerlink" title="可能用到的软件"></a>可能用到的软件</h3><p><a href="https://cdn.sevth.com/website/2020/04/14/ca90071a7d66ff9dead7e20be43b5697.zip">CloverConfigur5630</a></p>]]></content>
<summary type="html">
<blockquote>
<p>这篇文章仅针对于黑苹果用户,如果是白苹果,应该也是可以这么做的,本文仅提供参考,给一台非<code>mac</code>机器装上<code>Mac OS</code>系统称为黑苹果(hackintosh),虽然这违反了苹果公司的最终用户许可协议(<a href="/go/?f">EULA</a>,但是这是一种极客体验的方式。我不推荐这么做,并且最终选择权在你手中。</p>
<p>系统更新失败怎么办?启动界面多了一个烦人的图标?</p>
</blockquote>
</summary>
<category term="Mac" scheme="https://sevth.com/categories/Mac/"/>
<category term="tips" scheme="https://sevth.com/categories/Mac/tips/"/>
<category term="Mac" scheme="https://sevth.com/tags/Mac/"/>
<category term="clover" scheme="https://sevth.com/tags/clover/"/>
<category term="hackintosh" scheme="https://sevth.com/tags/hackintosh/"/>
</entry>
<entry>
<title>Mac小技巧:去掉更新设置小红点</title>
<link href="https://sevth.com/Mac/tips/Mac%E5%B0%8F%E6%8A%80%E5%B7%A7%EF%BC%9A%E5%8E%BB%E6%8E%89%E6%9B%B4%E6%96%B0%E8%AE%BE%E7%BD%AE%E5%B0%8F%E7%BA%A2%E7%82%B9.html"/>
<id>https://sevth.com/Mac/tips/Mac%E5%B0%8F%E6%8A%80%E5%B7%A7%EF%BC%9A%E5%8E%BB%E6%8E%89%E6%9B%B4%E6%96%B0%E8%AE%BE%E7%BD%AE%E5%B0%8F%E7%BA%A2%E7%82%B9.html</id>
<published>2020-04-14T05:38:00.000Z</published>
<updated>2020-04-26T10:35:31.059Z</updated>
<content type="html"><![CDATA[<blockquote><p>Mac 系统是苹果家的产品,自然而然地继承了苹果系列的一些“优点”,比如无时不刻在提醒着你更新,像是催命一样的提醒。假如我们并不想更新呢,或者已经更新了但是更新失败了怎么办?</p><p>Let’s Go!</p></blockquote><a id="more"></a><h2 id="讨厌的小红点就像下面一样"><a href="#讨厌的小红点就像下面一样" class="headerlink" title="讨厌的小红点就像下面一样"></a>讨厌的小红点就像下面一样</h2><p><img src="https://img.sevth.com/website/2020/04/14/4aa90e6de456543029873749af80bc97.png" alt="image-20200414140733567"></p><h2 id="操作指南"><a href="#操作指南" class="headerlink" title="操作指南"></a>操作指南</h2><h3 id="关闭系统的更新提醒"><a href="#关闭系统的更新提醒" class="headerlink" title="关闭系统的更新提醒"></a>关闭系统的更新提醒</h3><blockquote><p>打开设置->软件更新->高级->取消所有勾选 ☑️</p></blockquote><p>如下:</p><p><img src="https://img.sevth.com/website/2020/04/14/b050b4871fa037072baf7297e76a1557.png" alt="image-20200414141615901"></p><p>取消掉所有选项后,就不会自动检查更新,也不会提示你更新了。</p><h3 id="关闭小红点"><a href="#关闭小红点" class="headerlink" title="关闭小红点"></a>关闭小红点</h3><ol><li><p>打开启动台</p></li><li><p>直接输入 <code>ter</code> 搜索终端软件</p><p><img src="https://img.sevth.com/website/2020/04/14/74a06eac5979e44ec785ac541e666a42.png" alt="image-20200414143416202"></p></li><li><p>打开终端工具,输入如下的指令到终端</p><div class="highlight-container"><figure class=" highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">defaults write com.apple.systempreferences AttentionPrefBundleIDs 0</span><br></pre></td></tr></table></figure></div></li><li><p>重启 <code>Dock</code> (可选)</p><p>这个操作可以快速见效,就是桌面底部的 <code>Dock</code> 不再显示小红点。</p><div class="highlight-container"><figure class=" highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">killall Dock //注意大小写</span><br></pre></td></tr></table></figure></div></li><li><p>终极消除办法:重启电脑。将在设置界面也去掉小红点,只要不点开更新,一直有效。</p><p>相关指令输入参考:</p><p><img src="https://img.sevth.com/website/2020/04/14/644eff96d0546c649662d2b332bec825.png" alt="image-20200414144236479"></p><p>最终效果如下:</p><p><img src="https://img.sevth.com/website/2020/04/14/d3af2b56a9683993451d1f4921988f73.png" alt="image-20200414144553294"></p><p><img src="https://img.sevth.com/website/2020/04/14/630004aab6aeeb687c1ab16743157f66.png" alt="image-20200414144640675"></p><p><img src="https://img.sevth.com/website/2020/04/14/ac75111c43cca711220e4d8c07652b88.png" alt="image-20200414144614063"></p></li></ol>]]></content>
<summary type="html">
<blockquote>
<p>Mac 系统是苹果家的产品,自然而然地继承了苹果系列的一些“优点”,比如无时不刻在提醒着你更新,像是催命一样的提醒。假如我们并不想更新呢,或者已经更新了但是更新失败了怎么办?</p>
<p>Let’s Go!</p>
</blockquote>
</summary>
<category term="Mac" scheme="https://sevth.com/categories/Mac/"/>
<category term="tips" scheme="https://sevth.com/categories/Mac/tips/"/>
<category term="Mac" scheme="https://sevth.com/tags/Mac/"/>
<category term="hackintosh" scheme="https://sevth.com/tags/hackintosh/"/>
</entry>
<entry>
<title>“Markdown编辑器语法指南”</title>
<link href="https://sevth.com/reprint/Markdown%E7%BC%96%E8%BE%91%E5%99%A8%E8%AF%AD%E6%B3%95%E6%8C%87%E5%8D%97.html"/>
<id>https://sevth.com/reprint/Markdown%E7%BC%96%E8%BE%91%E5%99%A8%E8%AF%AD%E6%B3%95%E6%8C%87%E5%8D%97.html</id>
<published>2020-04-10T14:33:01.000Z</published>
<updated>2020-04-16T11:22:31.854Z</updated>
<content type="html"><</span><br><span class="line">网址链接 <http://链接网址></span><br></pre></td></tr></table></figure></div><p>高级链接技巧</p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">这个链接用 1 作为网址变量 [Google][1].</span><br><span class="line">这个链接用 yahoo 作为网址变量 [Yahoo!][yahoo].</span><br><span class="line">然后在文档的结尾为变量赋值(网址)</span><br><span class="line"></span><br><span class="line">[1]: http://www.google.com/</span><br><span class="line">[yahoo]: http://www.yahoo.com/</span><br></pre></td></tr></table></figure></div><h3 id="列表"><a href="#列表" class="headerlink" title="列表"></a>列表</h3><p>普通无序列表</p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">- 列表文本前使用 [减号+空格]</span><br><span class="line">+ 列表文本前使用 [加号+空格]</span><br><span class="line">* 列表文本前使用 [星号+空格]</span><br></pre></td></tr></table></figure></div><p>普通有序列表</p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">1. 列表前使用 [数字+空格]</span><br><span class="line">2. 我们会自动帮你添加数字</span><br><span class="line">7. 不用担心数字不对,显示的时候我们会自动把这行的 7 纠正为 3</span><br></pre></td></tr></table></figure></div><p>列表嵌套</p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">1. 列出所有元素:</span><br><span class="line"> - 无序列表元素 A</span><br><span class="line"> 1. 元素 A 的有序子列表</span><br><span class="line"> - 前面加四个空格</span><br><span class="line">2. 列表里的多段换行:</span><br><span class="line"> 前面必须加四个空格,</span><br><span class="line"> 这样换行,整体的格式不会乱</span><br><span class="line">3. 列表里引用:</span><br><span class="line"></span><br><span class="line"> > 前面空一行</span><br><span class="line"> > 仍然需要在 > 前面加四个空格</span><br><span class="line"></span><br><span class="line">4. 列表里代码段:</span><br><span class="line"></span><br><span class="line">(```)</span><br><span class="line"> 前面四个空格,之后按代码语法 (```) 书写</span><br><span class="line">(```)</span><br><span class="line"></span><br><span class="line"> 或者直接空八个,引入代码块</span><br></pre></td></tr></table></figure></div><h3 id="引用"><a href="#引用" class="headerlink" title="引用"></a>引用</h3><p>普通引用</p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">> 引用文本前使用 [大于号+空格]</span><br><span class="line">> 折行可以不加,新起一行都要加上哦</span><br></pre></td></tr></table></figure></div><p>引用里嵌套引用</p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">> 最外层引用</span><br><span class="line">> > 多一个 > 嵌套一层引用</span><br><span class="line">> ></span><br><span class="line">> > > 可以嵌套很多层</span><br></pre></td></tr></table></figure></div><p>引用里嵌套列表</p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">> - 这是引用里嵌套的一个列表</span><br><span class="line">> - 还可以有子列表</span><br><span class="line">> * 子列表需要从 - 之后延后四个空格开始</span><br></pre></td></tr></table></figure></div><p>引用里嵌套代码块</p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">> 同样的,在前面加四个空格形成代码块</span><br><span class="line">> </span><br><span class="line">> (```)</span><br><span class="line">> 或者使用 (```) 形成代码块</span><br><span class="line">> (```)</span><br></pre></td></tr></table></figure></div><h3 id="图片"><a href="#图片" class="headerlink" title="图片"></a>图片</h3><p>跟链接的方法区别在于前面加了个感叹号 <code>!</code>,这样是不是觉得好记多了呢?</p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"></span><br></pre></td></tr></table></figure></div><p>当然,你也可以像网址那样对图片网址使用变量</p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">这个链接用 1 作为网址变量 [Google][1].</span><br><span class="line">然后在文档的结尾位变量赋值(网址)</span><br><span class="line"></span><br><span class="line">[1]: http://www.google.com/logo.png</span><br></pre></td></tr></table></figure></div><h3 id="换行"><a href="#换行" class="headerlink" title="换行"></a>换行</h3><p>如果另起一行,只需在当前行结尾加 2 个空格</p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">在当前行的结尾加 2 个空格 </span><br><span class="line">这行就会新起一行</span><br></pre></td></tr></table></figure></div><p>如果是要起一个新段落,只需要空出一行即可。</p><h3 id="分隔符"><a href="#分隔符" class="headerlink" title="分隔符"></a>分隔符</h3><p>如果你有写分割线的习惯,可以新起一行输入三个减号<code>-</code>。当前后都有段落时,请空出一行:</p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">前面的段落</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line"></span><br><span class="line">后面的段落</span><br></pre></td></tr></table></figure></div><h2 id="高级技巧"><a href="#高级技巧" class="headerlink" title="高级技巧"></a>高级技巧</h2><h3 id="行内-HTML-元素"><a href="#行内-HTML-元素" class="headerlink" title="行内 HTML 元素"></a>行内 HTML 元素</h3><p>目前只支持部分段内 HTML 元素效果,包括 <code></code> ,如</p><p>键位显示</p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">使用 <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>Del</kbd> 重启电脑</span><br></pre></td></tr></table></figure></div><p>代码块</p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">使用 <pre></pre> 元素同样可以形成代码块</span><br></pre></td></tr></table></figure></div><p>粗斜体</p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><b> Markdown 在此处同样适用,如 *加粗* </b></span><br></pre></td></tr></table></figure></div><h3 id="符号转义"><a href="#符号转义" class="headerlink" title="符号转义"></a>符号转义</h3><p>如果你的描述中需要用到 markdown 的符号,比如 <code>_</code> <code>#</code> <code>*</code> 等,但又不想它被转义,这时候可以在这些符号前加反斜杠,如 <code>\_</code> <code>\#</code> <code>\*</code> 进行避免。</p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">\_不想这里的文本变斜体\_</span><br><span class="line">\*\*不想这里的文本被加粗\*\*</span><br></pre></td></tr></table></figure></div><h3 id="扩展"><a href="#扩展" class="headerlink" title="扩展"></a>扩展</h3><p>支持 <strong>jsfiddle、gist、runjs、优酷视频</strong>,直接填写 url,在其之后会自动添加预览点击会展开相关内容。</p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">http://{url_of_the_fiddle}/embedded/[{tabs}/[{style}]]/</span><br><span class="line">https://gist.github.com/{gist_id}</span><br><span class="line">http://runjs.cn/detail/{id}</span><br><span class="line">http://v.youku.com/v_show/id_{video_id}.html</span><br></pre></td></tr></table></figure></div><h3 id="公式"><a href="#公式" class="headerlink" title="公式"></a>公式</h3><p>当你需要在编辑器中插入数学公式时,可以使用两个美元符 $$ 包裹 TeX 或 LaTeX 格式的数学公式来实现。提交后,问答和文章页会根据需要加载 Mathjax 对数学公式进行渲染。如:</p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$$ x = {-b \pm \sqrt{b^2-4ac} \over 2a}. $$</span><br><span class="line"></span><br><span class="line">$$</span><br><span class="line">x \href{why-equal.html}{=} y^2 + 1</span><br><span class="line">$$</span><br></pre></td></tr></table></figure></div><p>同时也支持 HTML 属性,如:</p><div class="highlight-container"><figure class=" highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$$ (x+1)^2 = \class{hidden}{(x+1)(x+1)} $$</span><br><span class="line"></span><br><span class="line">$$</span><br><span class="line">(x+1)^2 = \cssId{step1}{\style{visibility:hidden}{(x+1)(x+1)}}</span><br><span class="line">$$</span><br></pre></td></tr></table></figure></div>]]></content>
<summary type="html">
<blockquote>
<p>Markdown是一种可以使用普通文本编辑器编写的<a href="https://baike.baidu.com/item/标记语言/5964436">标记语言</a>,通过简单的标记语法,它可以使普通文本内容具有一定的格式。</p>
</blockquote>
<blockquote>
<p>Tips: 本文仅方便自己学习作保存之用,<a href="https://segmentfault.com/markdown">点我阅读原文</a></p>
</blockquote>
</summary>
<category term="reprint" scheme="https://sevth.com/categories/reprint/"/>
<category term="markdown" scheme="https://sevth.com/tags/markdown/"/>
</entry>
<entry>
<title>Nginx配合CDN使用源站被暴露的问题</title>
<link href="https://sevth.com/technology/website/Nginx%E9%85%8D%E5%90%88CDN%E4%BD%BF%E7%94%A8%E6%BA%90%E7%AB%99%E8%A2%AB%E6%9A%B4%E9%9C%B2%E7%9A%84%E9%97%AE%E9%A2%98.html"/>
<id>https://sevth.com/technology/website/Nginx%E9%85%8D%E5%90%88CDN%E4%BD%BF%E7%94%A8%E6%BA%90%E7%AB%99%E8%A2%AB%E6%9A%B4%E9%9C%B2%E7%9A%84%E9%97%AE%E9%A2%98.html</id>
<published>2020-04-10T12:02:17.000Z</published>
<updated>2020-04-26T10:23:44.844Z</updated>
<content type="html"><![CDATA[<h4 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h4><blockquote><p><code>CDN</code> 即内容分发网络,<code>CDN</code>依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能,使用户就近获取所需的内容,降低网络阻塞,提高用户访问响应速度和命中率。 – 引用自<a href="/go/?6">《百度百科》</a></p><p><code>CDN</code>不仅具有加速的效果,更重要的是,保护源站安全,隐藏真实的源站信息。</p></blockquote><a id="more"></a><h4 id="问题分析"><a href="#问题分析" class="headerlink" title="问题分析"></a>问题分析</h4><p>在本博客部署之后,<code>CDN</code> 也用上了,然而出现了奇奇怪怪的问题。比如点击菜单栏的时候,自动跳转到源站域名去了,纳尼。这怎么能忍,于是敲开了 <code>Chrome</code> 的开发者工具(<kbd>F12</kbd> 打开)。 <code>Network</code> 选项卡查看到如下信息:</p><img src="https://img.sevth.com/website/2020/04/10/322cbc7aaf1a69d92e7dd73a5edbe52e.png" alt="image-20200410170952004" style="zoom: 67%;" /><h5 id="从图中看得到的信息"><a href="#从图中看得到的信息" class="headerlink" title="从图中看得到的信息"></a>从图中看得到的信息</h5><div class="highlight-container"><figure class=" highlight http"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attribute">request</span>: https://sevth.com/music -> response: https://xxxxxx/music/</span><br></pre></td></tr></table></figure></div><h5 id="我们可以知道的一些事情"><a href="#我们可以知道的一些事情" class="headerlink" title="我们可以知道的一些事情"></a>我们可以知道的一些事情</h5><p>首先,排除掉是 <code>CDN</code> 网络返回该状态码,一般情况下,<code>CDN</code>响应的内容都是根据源站的内容来响应的,不会主动响应某些内容。</p><p>然后我登录到服务查看 <code>Nginx</code> 日志,发现大量的 <code>301</code> 重定向。</p><p><img src="https://img.sevth.com/website/2020/04/10/6401a2da96471dda344e5ca1d6084b34.png" alt="image-20200410214208446"></p><p>这两条的记录区别就是,末尾带 <code>/</code> 的请求通过了,不带的被 <code>301</code> 重定向了,而且被重定向的地址还是绝对地址。</p><p>经过一番百度得知:</p><blockquote><p>Nginx主动设置301 Moved Permanently状态码只有一种情况,当用户输入了一个url地址,最后的部分是一个文件目录。比如 <code>http://www.test.com/index</code>, Nginx在运行过程中没有找到index这个文件,但发现了index是个目录。于是本次访问的状态码就会被设置成301 Moved Permanently。</p></blockquote><h4 id="解决问题"><a href="#解决问题" class="headerlink" title="解决问题"></a>解决问题</h4><p>知道了原因后,解决就简单了,让 <code>Nginx</code> 不返回绝对地址,返回相对地址不就行了呗。</p><div class="highlight-container"><figure class=" highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">server{</span><br><span class="line"> <span class="attribute">absolute_redirect</span> <span class="literal">off</span>;</span><br><span class="line"> </span><br><span class="line"> // 其它配置...</span><br><span class="line">}</span><br></pre></td></tr></table></figure></div><h4 id="查看结果"><a href="#查看结果" class="headerlink" title="查看结果"></a>查看结果</h4><p><img src="https://img.sevth.com/website/2020/04/10/7cdae9beadd9719f27026b274ee1be71.png" alt="image-20200410172154141"></p><p>这样就完美的解决了问题。</p><h4 id=""><a href="#" class="headerlink" title=""></a></h4><blockquote><p>参考链接: <a href="/go/?7">Nginx默认配置导致CDN源站泄露</a></p></blockquote>]]></content>
<summary type="html">
<h4 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h4><blockquote>
<p><code>CDN</code> 即内容分发网络,<code>CDN</code>依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能,使用户就近获取所需的内容,降低网络阻塞,提高用户访问响应速度和命中率。 – 引用自<a href="/go/?6">《百度百科》</a></p>
<p><code>CDN</code>不仅具有加速的效果,更重要的是,保护源站安全,隐藏真实的源站信息。</p>
</blockquote>
</summary>
<category term="technology" scheme="https://sevth.com/categories/technology/"/>
<category term="website" scheme="https://sevth.com/categories/technology/website/"/>
<category term="Nginx" scheme="https://sevth.com/tags/Nginx/"/>
<category term="CDN" scheme="https://sevth.com/tags/CDN/"/>
</entry>
</feed>