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

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

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
主站蜘蛛池模板: 69av美女| 日本ccc三级| 国产露脸对白刺激3p在线 | 色综合伊人色综合网亚洲欧洲 | 亚洲欧美日韩中文高清一 | 免费观看毛片视频 | 性关系视频免费网站在线观看 | 精品亚洲欧美中文字幕在线看 | 91大神在线观看精品一区 | 亚洲精品乱码蜜桃久久久 | 日本剧情片在线播放中文版 | 亚洲精品免费视频 | 91资源在线视频 | 亚洲天堂网站 | 成人精品一级毛片 | 国产色拍 | 视频一区二区三区欧美日韩 | 精品综合久久久久久8888 | 狠狠涩 | 国产精品嫩草影院在线看 | 国产精品久久国产精品99 | 国产精品一区二区久久 | 久久国产精品永久免费网站 | 欧美最猛性xxxxx动态图 | 美女和男生搞基 | 欧美va在线观看 | 国产成人综合手机在线播放 | 欧美日韩中文国产一区二区三区 | 玩50岁四川熟女大白屁股直播 | 动漫美女羞羞视频 | 国产午夜永久福利视频在线观看 | 国产乱子伦在线观看不卡 | 久久受www免费人成_看片中文 | 91制片厂制作传媒网站 | 9久热这里只有精品视频在线观看 | 亚洲男人天堂影院 | 免费在线观看网址入口 | 日韩一品在线播放视频一品免费 | 日本手机在线 | 美女脱了内裤打开腿让你桶爽 | 网址在线观看你懂我意思吧免费的 |