一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - IOS - iOS開發網絡篇—實現大文件的多線程斷點下載

iOS開發網絡篇—實現大文件的多線程斷點下載

2021-02-06 13:58文頂頂 IOS

iOS開發中經常會用到文件的下載功能,這篇文章主要介紹了iOS開發網絡篇—實現大文件的多線程斷點下載,今天咱們來分享一下思路。

說明:本文介紹多線程斷點下載。項目中使用了蘋果自帶的類,實現了同時開啟多條線程下載一個較大的文件。因為實現過程較為復雜,所以下面貼出完整的代碼。

實現思路:下載開始,創建一個和要下載的文件大小相同的文件(如果要下載的文件為100m,那么就在沙盒中創建一個100m的文件,然后計算每一段的下載量,開啟多條線程下載各段的數據,分別寫入對應的文件部分)。
iOS開發網絡篇—實現大文件的多線程斷點下載
項目中用到的主要類如下:
iOS開發網絡篇—實現大文件的多線程斷點下載

完成的實現代碼如下:

主控制器中的代碼:

?
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
#import "yyviewcontroller.h"
#import "yyfilemultidownloader.h"
 
@interface yyviewcontroller ()
@property (nonatomic, strong) yyfilemultidownloader *filemultidownloader;
@end
 
@implementation yyviewcontroller
- (yyfilemultidownloader *)filemultidownloader
{
  if (!_filemultidownloader) {
    _filemultidownloader = [[yyfilemultidownloader alloc] init];
    // 需要下載的文件遠程url
    _filemultidownloader.url = @"http://192.168.1.200:8080/mjserver/resources/jre.zip";
    // 文件保存到什么地方
    nsstring *caches = [nssearchpathfordirectoriesindomains(nscachesdirectory, nsuserdomainmask, yes) lastobject];
    nsstring *filepath = [caches stringbyappendingpathcomponent:@"jre.zip"];
    _filemultidownloader.destpath = filepath;
  }
  return _filemultidownloader;
}
 
- (void)viewdidload
{
  [super viewdidload];
  
}
 
- (void)touchesbegan:(nsset *)touches withevent:(uievent *)event
{
  [self.filemultidownloader start];
}
 
@end

自定義一個基類

yyfiledownloader.h文件

?
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
#import <foundation/foundation.h>
 
@interface yyfiledownloader : nsobject
{
  bool _downloading;
}
/**
 * 所需要下載文件的遠程url(連接服務器的路徑)
 */
@property (nonatomic, copy) nsstring *url;
/**
 * 文件的存儲路徑(文件下載到什么地方)
 */
@property (nonatomic, copy) nsstring *destpath;
 
/**
 * 是否正在下載(有沒有在下載, 只有下載器內部才知道)
 */
@property (nonatomic, readonly, getter = isdownloading) bool downloading;
 
/**
 * 用來監聽下載進度
 */
@property (nonatomic, copy) void (^progresshandler)(double progress);
 
/**
 * 開始(恢復)下載
 */
- (void)start;
 
/**
 * 暫停下載
 */
- (void)pause;
@end

yyfiledownloader.m文件

?
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
#import "yyfiledownloader.h"
 
@implementation yyfiledownloader
@end
下載器類繼承自yyfiledownloader這個類
 
yyfilesingdownloader.h文件
#import "yyfiledownloader.h"
 
@interface yyfilesingledownloader : yyfiledownloader
/**
 * 開始的位置
 */
@property (nonatomic, assign) long long begin;
/**
 * 結束的位置
 */
@property (nonatomic, assign) long long end;
@end
yyfilesingdownloader.m文件
#import "yyfilesingledownloader.h"
@interface yyfilesingledownloader() <nsurlconnectiondatadelegate>
/**
 * 連接對象
 */
@property (nonatomic, strong) nsurlconnection *conn;
 
/**
 * 寫數據的文件句柄
 */
@property (nonatomic, strong) nsfilehandle *writehandle;
/**
 * 當前已下載數據的長度
 */
@property (nonatomic, assign) long long currentlength;
@end
 
@implementation yyfilesingledownloader
 
- (nsfilehandle *)writehandle
{
  if (!_writehandle) {
    _writehandle = [nsfilehandle filehandleforwritingatpath:self.destpath];
  }
  return _writehandle;
}
 
/**
 * 開始(恢復)下載
 */
- (void)start
{
  nsurl *url = [nsurl urlwithstring:self.url];
  // 默認就是get請求
  nsmutableurlrequest *request = [nsmutableurlrequest requestwithurl:url];
  // 設置請求頭信息
  nsstring *value = [nsstring stringwithformat:@"bytes=%lld-%lld", self.begin + self.currentlength, self.end];
  [request setvalue:value forhttpheaderfield:@"range"];
  self.conn = [nsurlconnection connectionwithrequest:request delegate:self];
  
  _downloading = yes;
}
 
/**
 * 暫停下載
 */
- (void)pause
{
  [self.conn cancel];
  self.conn = nil;
  
  _downloading = no;
}
 
 
#pragma mark - nsurlconnectiondatadelegate 代理方法
/**
 * 1. 當接受到服務器的響應(連通了服務器)就會調用
 */
- (void)connection:(nsurlconnection *)connection didreceiveresponse:(nsurlresponse *)response
{
  
}
 
/**
 * 2. 當接受到服務器的數據就會調用(可能會被調用多次, 每次調用只會傳遞部分數據)
 */
- (void)connection:(nsurlconnection *)connection didreceivedata:(nsdata *)data
{
  // 移動到文件的尾部
  [self.writehandle seektofileoffset:self.begin + self.currentlength];
  // 從當前移動的位置(文件尾部)開始寫入數據
  [self.writehandle writedata:data];
  
  // 累加長度
  self.currentlength += data.length;
  
  // 打印下載進度
  double progress = (double)self.currentlength / (self.end - self.begin);
  if (self.progresshandler) {
    self.progresshandler(progress);
  }
}
 
/**
 * 3. 當服務器的數據接受完畢后就會調用
 */
- (void)connectiondidfinishloading:(nsurlconnection *)connection
{
  // 清空屬性值
  self.currentlength = 0;
  
  // 關閉連接(不再輸入數據到文件中)
  [self.writehandle closefile];
  self.writehandle = nil;
}
 
/**
 * 請求錯誤(失敗)的時候調用(請求超時\斷網\沒有網, 一般指客戶端錯誤)
 */
- (void)connection:(nsurlconnection *)connection didfailwitherror:(nserror *)error
{
  
}
 
@end

設計多線程下載器(利用hmfilemultidownloader能開啟多個線程同時下載一個文件)

一個多線程下載器只下載一個文件

yyfilemultidownloader.h文件

?
1
2
3
#import "yyfiledownloader.h"
@interface yyfilemultidownloader : yyfiledownloader
@end

yyfilemultidownloader.m文件

?
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
#import "yyfilemultidownloader.h"
#import "yyfilesingledownloader.h"
 
#define yymaxdownloadcount 4
 
@interface yyfilemultidownloader()
@property (nonatomic, strong) nsmutablearray *singledownloaders;
@property (nonatomic, assign) long long totallength;
@end
 
@implementation yyfilemultidownloader
 
- (void)getfilesize
{
  nsmutableurlrequest *request = [nsmutableurlrequest requestwithurl:[nsurl urlwithstring:self.url]];
  request.httpmethod = @"head";
  
  nsurlresponse *response = nil;
#warning 這里要用異步請求
  [nsurlconnection sendsynchronousrequest:request returningresponse:&response error:nil];
  self.totallength = response.expectedcontentlength;
}
 
- (nsmutablearray *)singledownloaders
{
  if (!_singledownloaders) {
    _singledownloaders = [nsmutablearray array];
    
    // 獲得文件大小
    [self getfilesize];
    
    // 每條路徑的下載量
    long long size = 0;
    if (self.totallength % yymaxdownloadcount == 0) {
      size = self.totallength / yymaxdownloadcount;
    } else {
      size = self.totallength / yymaxdownloadcount + 1;
    }
    
    // 創建n個下載器
    for (int i = 0; i<yymaxdownloadcount; i++) {
      yyfilesingledownloader *singledownloader = [[yyfilesingledownloader alloc] init];
      singledownloader.url = self.url;
      singledownloader.destpath = self.destpath;
      singledownloader.begin = i * size;
      singledownloader.end = singledownloader.begin + size - 1;
      singledownloader.progresshandler = ^(double progress){
        nslog(@"%d --- %f", i, progress);
      };
      [_singledownloaders addobject:singledownloader];
    }
    
    // 創建一個跟服務器文件等大小的臨時文件
    [[nsfilemanager defaultmanager] createfileatpath:self.destpath contents:nil attributes:nil];
    
    // 讓self.destpath文件的長度是self.totallengt
    nsfilehandle *handle = [nsfilehandle filehandleforwritingatpath:self.destpath];
    [handle truncatefileatoffset:self.totallength];
  }
  return _singledownloaders;
}
 
/**
 * 開始(恢復)下載
 */
- (void)start
{
  [self.singledownloaders makeobjectsperformselector:@selector(start)];
  
  _downloading = yes;
}
 
/**
 * 暫停下載
 */
- (void)pause
{
  [self.singledownloaders makeobjectsperformselector:@selector(pause)];
  _downloading = no;
}
 
@end

補充說明:如何獲得將要下載的文件的大小?iOS開發網絡篇—實現大文件的多線程斷點下載
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

延伸 · 閱讀

精彩推薦
  • IOSiOS中滑動控制屏幕亮度和系統音量(附加AVAudioPlayer基本用法和Masonry簡單使用)

    iOS中滑動控制屏幕亮度和系統音量(附加AVAudioPlayer基本用法和

    這篇文章主要介紹了iOS中滑動控制屏幕亮度和系統音量(附加AVAudioPlayer基本用法和Masonry簡單使用)的相關資料,需要的朋友可以參考下...

    CodingFire13652021-02-26
  • IOSiOS自定義UICollectionViewFlowLayout實現圖片瀏覽效果

    iOS自定義UICollectionViewFlowLayout實現圖片瀏覽效果

    這篇文章主要介紹了iOS自定義UICollectionViewFlowLayout實現圖片瀏覽效果的相關資料,需要的朋友可以參考下...

    jiangamh8882021-01-11
  • IOSiOS開發技巧之狀態欄字體顏色的設置方法

    iOS開發技巧之狀態欄字體顏色的設置方法

    有時候我們需要根據不同的背景修改狀態欄字體的顏色,下面這篇文章主要給大家介紹了關于iOS開發技巧之狀態欄字體顏色的設置方法,文中通過示例代碼...

    夢想家-mxj8922021-05-10
  • IOSiOS開發之視圖切換

    iOS開發之視圖切換

    在iOS開發中視圖的切換是很頻繁的,獨立的視圖應用在實際開發過程中并不常見,除非你的應用足夠簡單。在iOS開發中常用的視圖切換有三種,今天我們將...

    執著丶執念5282021-01-16
  • IOS詳解iOS中多個網絡請求的同步問題總結

    詳解iOS中多個網絡請求的同步問題總結

    這篇文章主要介紹了詳解iOS中多個網絡請求的同步問題總結,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧...

    liang199111312021-03-15
  • IOSiOS中UILabel實現長按復制功能實例代碼

    iOS中UILabel實現長按復制功能實例代碼

    在iOS開發過程中,有時候會用到UILabel展示的內容,那么就設計到點擊UILabel復制它上面展示的內容的功能,也就是Label長按復制功能,下面這篇文章主要給大...

    devilx12792021-04-02
  • IOSiOS中MD5加密算法的介紹和使用

    iOS中MD5加密算法的介紹和使用

    MD5加密是最常用的加密方法之一,是從一段字符串中通過相應特征生成一段32位的數字字母混合碼。對輸入信息生成唯一的128位散列值(32個字符)。這篇文...

    LYSNote5432021-02-04
  • IOSiOS實現控制屏幕常亮不變暗的方法示例

    iOS實現控制屏幕常亮不變暗的方法示例

    最近在工作中遇到了要將iOS屏幕保持常亮的需求,所以下面這篇文章主要給大家介紹了關于利用iOS如何實現控制屏幕常亮不變暗的方法,文中給出了詳細的...

    隨風13332021-04-02
主站蜘蛛池模板: 无人影院在线播放视频 | 欧洲兽皇 | 男生同性啪视频在线观看 | 国产成人在线免费视频 | 99热久久国产精品这里 | 继的朋友无遮漫画免费观看73 | 91李宗精品72集在线观看 | 国产福利微拍精品一区二区 | xxx86日本人 xxnx日本免费护士 | 国产午夜精品理论片 | 精品视频国产 | 大伊香蕉精品视频一区 | 无码AV精品一区二区三区 | 午夜免费无码福利视频麻豆 | 99国内精品久久久久久久黑人 | 嗯啊好爽视频 | 九九热这里只有精品2 | 亚洲国产精品ⅴa在线观看 亚洲国产高清一区二区三区 | 我们日本在线观看免费动漫下载 | 99re5精品视频在线观看 | 国产欧美日韩精品一区二区三区 | 9久热这里只有精品免费 | 日韩精品亚洲一级在线观看 | 亚洲丁香网 | 国产一区视频在线免费观看 | 999久久免费高清热精品 | 午夜爱情动作片P | 国产成人精品视频频 | 99久久er这里只有精品17 | www伊人 | 亚洲精品福利你懂 | 日韩欧美一区二区三区中文精品 | 香蕉久久高清国产精品免费 | 嗯啊视频在线观看 | 色老板在线观看 | 毛片a级放荡的护士hd | 精品国产一区二区三区在线观看 | 国产成+人+综合+欧美 亚洲 | 女人和男人搞基 | 国产东北3p真实在线456视频 | 天天爽视频 |