├── .gitignore ├── LICENSE ├── README.md ├── UploadExamples ├── UploadExamples.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── UploadExamples │ ├── 111 │ ├── 222 │ ├── AFNetworking │ │ ├── AFHTTPRequestOperation.h │ │ ├── AFHTTPRequestOperation.m │ │ ├── AFHTTPRequestOperationManager.h │ │ ├── AFHTTPRequestOperationManager.m │ │ ├── AFHTTPSessionManager.h │ │ ├── AFHTTPSessionManager.m │ │ ├── AFNetworkReachabilityManager.h │ │ ├── AFNetworkReachabilityManager.m │ │ ├── AFNetworking.h │ │ ├── AFSecurityPolicy.h │ │ ├── AFSecurityPolicy.m │ │ ├── AFURLConnectionOperation.h │ │ ├── AFURLConnectionOperation.m │ │ ├── AFURLRequestSerialization.h │ │ ├── AFURLRequestSerialization.m │ │ ├── AFURLResponseSerialization.h │ │ ├── AFURLResponseSerialization.m │ │ ├── AFURLSessionManager.h │ │ └── AFURLSessionManager.m │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ ├── ViewController.h │ ├── ViewController.m │ └── main.m └── UploadExamplesTests │ ├── Info.plist │ └── UploadExamplesTests.m └── UploadRequest ├── NSMutableURLRequest+Upload.h └── NSMutableURLRequest+Upload.m /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | # Pods/ 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Fan Liu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NSMutableURLRequest-Upload 2 | 3 | 4 | 针对文件上传的 NSMutableURLRequest 分类 5 | 6 | 7 | ## 使用 8 | 9 | - 添加分类文件 10 | 11 | 将 `UploadRequest` 目录直接拖动到项目中 12 | 13 | - 导入分类头文件 14 | 15 | ``` 16 | #import "NSMutableURLRequest+Upload.h" 17 | ``` 18 | - 上传单个文件的请求 19 | 20 | ``` 21 | NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"local.txt" withExtension:nil]; 22 | 23 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url fileURL:fileURL fileName:@"remote.txt" name:@"userfile"]; 24 | ``` 25 | 26 | - 上传多个文件的请求 27 | 28 | ``` 29 | NSArray *fileURLs = @[[[NSBundle mainBundle] URLForResource:@"local1.txt" withExtension:nil], 30 | [[NSBundle mainBundle] URLForResource:@"local2.txt" withExtension:nil]]; 31 | NSArray *fileNames = @[@"remote1.txt", @"remote2.txt"]; 32 | 33 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url fileURLs:fileURLs fileNames:fileNames name:@"userfile"]; 34 | ``` 35 | 36 | 37 | ## multipart/form-data POST 上传请求数据体格式 38 | 39 | ### 上传单个文件 40 | 41 | ``` 42 | \r\n--boundary\r\n 43 | Content-Disposition: form-data; name="userfile"; filename="filename"\r\n 44 | Content-Type: application/octet-stream\r\n\r\n 45 | // 上传文件的二进制数据 46 | \r\n 47 | --boundary--\r\n 48 | ``` 49 | 50 | #### 参数说明 51 | 52 | - boundary: 有字母和数字组成的随机字符串 53 | - **userfile**: 服务器脚本中负责上传文件的字段名 54 | - filename: 保存在服务器上的文件名 55 | 56 | ### 上传多个文件 57 | 58 | ``` 59 | \r\n--boundary\r\n 60 | Content-Disposition: form-data; name="userfile[]"; filename="filename1"\r\n 61 | Content-Type: application/octet-stream\r\n\r\n 62 | // 第一个上传文件的二进制数据 63 | \r\n 64 | \r\n--boundary\r\n 65 | Content-Disposition: form-data; name="userfile[]"; filename="filename2"\r\n 66 | Content-Type: application/octet-stream\r\n\r\n 67 | // 第一个上传文件的二进制数据 68 | \r\n 69 | --boundary--\r\n 70 | ``` 71 | 72 | #### 参数说明 73 | 74 | - boundary: 有字母和数字组成的随机字符串 75 | - **userfile[]**: 服务器脚本中负责上传文件的字段名 76 | - filename: 保存在服务器上的文件名 77 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | C2D67ABC1A7CF001005989A2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C2D67ABB1A7CF001005989A2 /* main.m */; }; 11 | C2D67ABF1A7CF001005989A2 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C2D67ABE1A7CF001005989A2 /* AppDelegate.m */; }; 12 | C2D67AC21A7CF001005989A2 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C2D67AC11A7CF001005989A2 /* ViewController.m */; }; 13 | C2D67AC51A7CF001005989A2 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C2D67AC31A7CF001005989A2 /* Main.storyboard */; }; 14 | C2D67AC71A7CF001005989A2 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C2D67AC61A7CF001005989A2 /* Images.xcassets */; }; 15 | C2D67ACA1A7CF001005989A2 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = C2D67AC81A7CF001005989A2 /* LaunchScreen.xib */; }; 16 | C2D67AD61A7CF001005989A2 /* UploadExamplesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C2D67AD51A7CF001005989A2 /* UploadExamplesTests.m */; }; 17 | C2D67AE51A7CF381005989A2 /* 111 in Resources */ = {isa = PBXBuildFile; fileRef = C2D67AE31A7CF381005989A2 /* 111 */; }; 18 | C2D67AE61A7CF381005989A2 /* 222 in Resources */ = {isa = PBXBuildFile; fileRef = C2D67AE41A7CF381005989A2 /* 222 */; }; 19 | C2D67AEA1A7D01E6005989A2 /* NSMutableURLRequest+Upload.m in Sources */ = {isa = PBXBuildFile; fileRef = C2D67AE91A7D01E6005989A2 /* NSMutableURLRequest+Upload.m */; }; 20 | C2D67AFF1A7D02BB005989A2 /* AFHTTPRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = C2D67AED1A7D02BB005989A2 /* AFHTTPRequestOperation.m */; }; 21 | C2D67B001A7D02BB005989A2 /* AFHTTPRequestOperationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C2D67AEF1A7D02BB005989A2 /* AFHTTPRequestOperationManager.m */; }; 22 | C2D67B011A7D02BB005989A2 /* AFHTTPSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C2D67AF11A7D02BB005989A2 /* AFHTTPSessionManager.m */; }; 23 | C2D67B021A7D02BB005989A2 /* AFNetworkReachabilityManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C2D67AF41A7D02BB005989A2 /* AFNetworkReachabilityManager.m */; }; 24 | C2D67B031A7D02BB005989A2 /* AFSecurityPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = C2D67AF61A7D02BB005989A2 /* AFSecurityPolicy.m */; }; 25 | C2D67B041A7D02BB005989A2 /* AFURLConnectionOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = C2D67AF81A7D02BB005989A2 /* AFURLConnectionOperation.m */; }; 26 | C2D67B051A7D02BB005989A2 /* AFURLRequestSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = C2D67AFA1A7D02BB005989A2 /* AFURLRequestSerialization.m */; }; 27 | C2D67B061A7D02BB005989A2 /* AFURLResponseSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = C2D67AFC1A7D02BB005989A2 /* AFURLResponseSerialization.m */; }; 28 | C2D67B071A7D02BB005989A2 /* AFURLSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C2D67AFE1A7D02BB005989A2 /* AFURLSessionManager.m */; }; 29 | /* End PBXBuildFile section */ 30 | 31 | /* Begin PBXContainerItemProxy section */ 32 | C2D67AD01A7CF001005989A2 /* PBXContainerItemProxy */ = { 33 | isa = PBXContainerItemProxy; 34 | containerPortal = C2D67AAE1A7CF001005989A2 /* Project object */; 35 | proxyType = 1; 36 | remoteGlobalIDString = C2D67AB51A7CF001005989A2; 37 | remoteInfo = UploadExamples; 38 | }; 39 | /* End PBXContainerItemProxy section */ 40 | 41 | /* Begin PBXFileReference section */ 42 | C2D67AB61A7CF001005989A2 /* UploadExamples.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UploadExamples.app; sourceTree = BUILT_PRODUCTS_DIR; }; 43 | C2D67ABA1A7CF001005989A2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 44 | C2D67ABB1A7CF001005989A2 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 45 | C2D67ABD1A7CF001005989A2 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 46 | C2D67ABE1A7CF001005989A2 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 47 | C2D67AC01A7CF001005989A2 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 48 | C2D67AC11A7CF001005989A2 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 49 | C2D67AC41A7CF001005989A2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 50 | C2D67AC61A7CF001005989A2 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 51 | C2D67AC91A7CF001005989A2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 52 | C2D67ACF1A7CF001005989A2 /* UploadExamplesTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UploadExamplesTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 53 | C2D67AD41A7CF001005989A2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 54 | C2D67AD51A7CF001005989A2 /* UploadExamplesTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UploadExamplesTests.m; sourceTree = ""; }; 55 | C2D67AE31A7CF381005989A2 /* 111 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = 111; sourceTree = ""; }; 56 | C2D67AE41A7CF381005989A2 /* 222 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = 222; sourceTree = ""; }; 57 | C2D67AE81A7D01E6005989A2 /* NSMutableURLRequest+Upload.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableURLRequest+Upload.h"; sourceTree = ""; }; 58 | C2D67AE91A7D01E6005989A2 /* NSMutableURLRequest+Upload.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableURLRequest+Upload.m"; sourceTree = ""; }; 59 | C2D67AEC1A7D02BB005989A2 /* AFHTTPRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFHTTPRequestOperation.h; sourceTree = ""; }; 60 | C2D67AED1A7D02BB005989A2 /* AFHTTPRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPRequestOperation.m; sourceTree = ""; }; 61 | C2D67AEE1A7D02BB005989A2 /* AFHTTPRequestOperationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFHTTPRequestOperationManager.h; sourceTree = ""; }; 62 | C2D67AEF1A7D02BB005989A2 /* AFHTTPRequestOperationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPRequestOperationManager.m; sourceTree = ""; }; 63 | C2D67AF01A7D02BB005989A2 /* AFHTTPSessionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFHTTPSessionManager.h; sourceTree = ""; }; 64 | C2D67AF11A7D02BB005989A2 /* AFHTTPSessionManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPSessionManager.m; sourceTree = ""; }; 65 | C2D67AF21A7D02BB005989A2 /* AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFNetworking.h; sourceTree = ""; }; 66 | C2D67AF31A7D02BB005989A2 /* AFNetworkReachabilityManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFNetworkReachabilityManager.h; sourceTree = ""; }; 67 | C2D67AF41A7D02BB005989A2 /* AFNetworkReachabilityManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFNetworkReachabilityManager.m; sourceTree = ""; }; 68 | C2D67AF51A7D02BB005989A2 /* AFSecurityPolicy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFSecurityPolicy.h; sourceTree = ""; }; 69 | C2D67AF61A7D02BB005989A2 /* AFSecurityPolicy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFSecurityPolicy.m; sourceTree = ""; }; 70 | C2D67AF71A7D02BB005989A2 /* AFURLConnectionOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFURLConnectionOperation.h; sourceTree = ""; }; 71 | C2D67AF81A7D02BB005989A2 /* AFURLConnectionOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFURLConnectionOperation.m; sourceTree = ""; }; 72 | C2D67AF91A7D02BB005989A2 /* AFURLRequestSerialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFURLRequestSerialization.h; sourceTree = ""; }; 73 | C2D67AFA1A7D02BB005989A2 /* AFURLRequestSerialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFURLRequestSerialization.m; sourceTree = ""; }; 74 | C2D67AFB1A7D02BB005989A2 /* AFURLResponseSerialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFURLResponseSerialization.h; sourceTree = ""; }; 75 | C2D67AFC1A7D02BB005989A2 /* AFURLResponseSerialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFURLResponseSerialization.m; sourceTree = ""; }; 76 | C2D67AFD1A7D02BB005989A2 /* AFURLSessionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFURLSessionManager.h; sourceTree = ""; }; 77 | C2D67AFE1A7D02BB005989A2 /* AFURLSessionManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFURLSessionManager.m; sourceTree = ""; }; 78 | /* End PBXFileReference section */ 79 | 80 | /* Begin PBXFrameworksBuildPhase section */ 81 | C2D67AB31A7CF001005989A2 /* Frameworks */ = { 82 | isa = PBXFrameworksBuildPhase; 83 | buildActionMask = 2147483647; 84 | files = ( 85 | ); 86 | runOnlyForDeploymentPostprocessing = 0; 87 | }; 88 | C2D67ACC1A7CF001005989A2 /* Frameworks */ = { 89 | isa = PBXFrameworksBuildPhase; 90 | buildActionMask = 2147483647; 91 | files = ( 92 | ); 93 | runOnlyForDeploymentPostprocessing = 0; 94 | }; 95 | /* End PBXFrameworksBuildPhase section */ 96 | 97 | /* Begin PBXGroup section */ 98 | C2D67AAD1A7CF001005989A2 = { 99 | isa = PBXGroup; 100 | children = ( 101 | C2D67AB81A7CF001005989A2 /* UploadExamples */, 102 | C2D67AD21A7CF001005989A2 /* UploadExamplesTests */, 103 | C2D67AB71A7CF001005989A2 /* Products */, 104 | ); 105 | sourceTree = ""; 106 | }; 107 | C2D67AB71A7CF001005989A2 /* Products */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | C2D67AB61A7CF001005989A2 /* UploadExamples.app */, 111 | C2D67ACF1A7CF001005989A2 /* UploadExamplesTests.xctest */, 112 | ); 113 | name = Products; 114 | sourceTree = ""; 115 | }; 116 | C2D67AB81A7CF001005989A2 /* UploadExamples */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | C2D67AEB1A7D02BB005989A2 /* AFNetworking */, 120 | C2D67AE71A7D01E6005989A2 /* UploadRequest */, 121 | C2D67ABD1A7CF001005989A2 /* AppDelegate.h */, 122 | C2D67ABE1A7CF001005989A2 /* AppDelegate.m */, 123 | C2D67AC01A7CF001005989A2 /* ViewController.h */, 124 | C2D67AC11A7CF001005989A2 /* ViewController.m */, 125 | C2D67AC31A7CF001005989A2 /* Main.storyboard */, 126 | C2D67AC61A7CF001005989A2 /* Images.xcassets */, 127 | C2D67AC81A7CF001005989A2 /* LaunchScreen.xib */, 128 | C2D67AB91A7CF001005989A2 /* Supporting Files */, 129 | ); 130 | path = UploadExamples; 131 | sourceTree = ""; 132 | }; 133 | C2D67AB91A7CF001005989A2 /* Supporting Files */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | C2D67AE31A7CF381005989A2 /* 111 */, 137 | C2D67AE41A7CF381005989A2 /* 222 */, 138 | C2D67ABA1A7CF001005989A2 /* Info.plist */, 139 | C2D67ABB1A7CF001005989A2 /* main.m */, 140 | ); 141 | name = "Supporting Files"; 142 | sourceTree = ""; 143 | }; 144 | C2D67AD21A7CF001005989A2 /* UploadExamplesTests */ = { 145 | isa = PBXGroup; 146 | children = ( 147 | C2D67AD51A7CF001005989A2 /* UploadExamplesTests.m */, 148 | C2D67AD31A7CF001005989A2 /* Supporting Files */, 149 | ); 150 | path = UploadExamplesTests; 151 | sourceTree = ""; 152 | }; 153 | C2D67AD31A7CF001005989A2 /* Supporting Files */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | C2D67AD41A7CF001005989A2 /* Info.plist */, 157 | ); 158 | name = "Supporting Files"; 159 | sourceTree = ""; 160 | }; 161 | C2D67AE71A7D01E6005989A2 /* UploadRequest */ = { 162 | isa = PBXGroup; 163 | children = ( 164 | C2D67AE81A7D01E6005989A2 /* NSMutableURLRequest+Upload.h */, 165 | C2D67AE91A7D01E6005989A2 /* NSMutableURLRequest+Upload.m */, 166 | ); 167 | name = UploadRequest; 168 | path = ../../UploadRequest; 169 | sourceTree = ""; 170 | }; 171 | C2D67AEB1A7D02BB005989A2 /* AFNetworking */ = { 172 | isa = PBXGroup; 173 | children = ( 174 | C2D67AEC1A7D02BB005989A2 /* AFHTTPRequestOperation.h */, 175 | C2D67AED1A7D02BB005989A2 /* AFHTTPRequestOperation.m */, 176 | C2D67AEE1A7D02BB005989A2 /* AFHTTPRequestOperationManager.h */, 177 | C2D67AEF1A7D02BB005989A2 /* AFHTTPRequestOperationManager.m */, 178 | C2D67AF01A7D02BB005989A2 /* AFHTTPSessionManager.h */, 179 | C2D67AF11A7D02BB005989A2 /* AFHTTPSessionManager.m */, 180 | C2D67AF21A7D02BB005989A2 /* AFNetworking.h */, 181 | C2D67AF31A7D02BB005989A2 /* AFNetworkReachabilityManager.h */, 182 | C2D67AF41A7D02BB005989A2 /* AFNetworkReachabilityManager.m */, 183 | C2D67AF51A7D02BB005989A2 /* AFSecurityPolicy.h */, 184 | C2D67AF61A7D02BB005989A2 /* AFSecurityPolicy.m */, 185 | C2D67AF71A7D02BB005989A2 /* AFURLConnectionOperation.h */, 186 | C2D67AF81A7D02BB005989A2 /* AFURLConnectionOperation.m */, 187 | C2D67AF91A7D02BB005989A2 /* AFURLRequestSerialization.h */, 188 | C2D67AFA1A7D02BB005989A2 /* AFURLRequestSerialization.m */, 189 | C2D67AFB1A7D02BB005989A2 /* AFURLResponseSerialization.h */, 190 | C2D67AFC1A7D02BB005989A2 /* AFURLResponseSerialization.m */, 191 | C2D67AFD1A7D02BB005989A2 /* AFURLSessionManager.h */, 192 | C2D67AFE1A7D02BB005989A2 /* AFURLSessionManager.m */, 193 | ); 194 | path = AFNetworking; 195 | sourceTree = ""; 196 | }; 197 | /* End PBXGroup section */ 198 | 199 | /* Begin PBXNativeTarget section */ 200 | C2D67AB51A7CF001005989A2 /* UploadExamples */ = { 201 | isa = PBXNativeTarget; 202 | buildConfigurationList = C2D67AD91A7CF001005989A2 /* Build configuration list for PBXNativeTarget "UploadExamples" */; 203 | buildPhases = ( 204 | C2D67AB21A7CF001005989A2 /* Sources */, 205 | C2D67AB31A7CF001005989A2 /* Frameworks */, 206 | C2D67AB41A7CF001005989A2 /* Resources */, 207 | ); 208 | buildRules = ( 209 | ); 210 | dependencies = ( 211 | ); 212 | name = UploadExamples; 213 | productName = UploadExamples; 214 | productReference = C2D67AB61A7CF001005989A2 /* UploadExamples.app */; 215 | productType = "com.apple.product-type.application"; 216 | }; 217 | C2D67ACE1A7CF001005989A2 /* UploadExamplesTests */ = { 218 | isa = PBXNativeTarget; 219 | buildConfigurationList = C2D67ADC1A7CF001005989A2 /* Build configuration list for PBXNativeTarget "UploadExamplesTests" */; 220 | buildPhases = ( 221 | C2D67ACB1A7CF001005989A2 /* Sources */, 222 | C2D67ACC1A7CF001005989A2 /* Frameworks */, 223 | C2D67ACD1A7CF001005989A2 /* Resources */, 224 | ); 225 | buildRules = ( 226 | ); 227 | dependencies = ( 228 | C2D67AD11A7CF001005989A2 /* PBXTargetDependency */, 229 | ); 230 | name = UploadExamplesTests; 231 | productName = UploadExamplesTests; 232 | productReference = C2D67ACF1A7CF001005989A2 /* UploadExamplesTests.xctest */; 233 | productType = "com.apple.product-type.bundle.unit-test"; 234 | }; 235 | /* End PBXNativeTarget section */ 236 | 237 | /* Begin PBXProject section */ 238 | C2D67AAE1A7CF001005989A2 /* Project object */ = { 239 | isa = PBXProject; 240 | attributes = { 241 | LastUpgradeCheck = 0610; 242 | ORGANIZATIONNAME = joyios; 243 | TargetAttributes = { 244 | C2D67AB51A7CF001005989A2 = { 245 | CreatedOnToolsVersion = 6.1.1; 246 | }; 247 | C2D67ACE1A7CF001005989A2 = { 248 | CreatedOnToolsVersion = 6.1.1; 249 | TestTargetID = C2D67AB51A7CF001005989A2; 250 | }; 251 | }; 252 | }; 253 | buildConfigurationList = C2D67AB11A7CF001005989A2 /* Build configuration list for PBXProject "UploadExamples" */; 254 | compatibilityVersion = "Xcode 3.2"; 255 | developmentRegion = English; 256 | hasScannedForEncodings = 0; 257 | knownRegions = ( 258 | en, 259 | Base, 260 | ); 261 | mainGroup = C2D67AAD1A7CF001005989A2; 262 | productRefGroup = C2D67AB71A7CF001005989A2 /* Products */; 263 | projectDirPath = ""; 264 | projectRoot = ""; 265 | targets = ( 266 | C2D67AB51A7CF001005989A2 /* UploadExamples */, 267 | C2D67ACE1A7CF001005989A2 /* UploadExamplesTests */, 268 | ); 269 | }; 270 | /* End PBXProject section */ 271 | 272 | /* Begin PBXResourcesBuildPhase section */ 273 | C2D67AB41A7CF001005989A2 /* Resources */ = { 274 | isa = PBXResourcesBuildPhase; 275 | buildActionMask = 2147483647; 276 | files = ( 277 | C2D67AC51A7CF001005989A2 /* Main.storyboard in Resources */, 278 | C2D67AE61A7CF381005989A2 /* 222 in Resources */, 279 | C2D67ACA1A7CF001005989A2 /* LaunchScreen.xib in Resources */, 280 | C2D67AE51A7CF381005989A2 /* 111 in Resources */, 281 | C2D67AC71A7CF001005989A2 /* Images.xcassets in Resources */, 282 | ); 283 | runOnlyForDeploymentPostprocessing = 0; 284 | }; 285 | C2D67ACD1A7CF001005989A2 /* Resources */ = { 286 | isa = PBXResourcesBuildPhase; 287 | buildActionMask = 2147483647; 288 | files = ( 289 | ); 290 | runOnlyForDeploymentPostprocessing = 0; 291 | }; 292 | /* End PBXResourcesBuildPhase section */ 293 | 294 | /* Begin PBXSourcesBuildPhase section */ 295 | C2D67AB21A7CF001005989A2 /* Sources */ = { 296 | isa = PBXSourcesBuildPhase; 297 | buildActionMask = 2147483647; 298 | files = ( 299 | C2D67AC21A7CF001005989A2 /* ViewController.m in Sources */, 300 | C2D67B031A7D02BB005989A2 /* AFSecurityPolicy.m in Sources */, 301 | C2D67ABF1A7CF001005989A2 /* AppDelegate.m in Sources */, 302 | C2D67B001A7D02BB005989A2 /* AFHTTPRequestOperationManager.m in Sources */, 303 | C2D67B041A7D02BB005989A2 /* AFURLConnectionOperation.m in Sources */, 304 | C2D67AFF1A7D02BB005989A2 /* AFHTTPRequestOperation.m in Sources */, 305 | C2D67AEA1A7D01E6005989A2 /* NSMutableURLRequest+Upload.m in Sources */, 306 | C2D67B051A7D02BB005989A2 /* AFURLRequestSerialization.m in Sources */, 307 | C2D67B011A7D02BB005989A2 /* AFHTTPSessionManager.m in Sources */, 308 | C2D67B021A7D02BB005989A2 /* AFNetworkReachabilityManager.m in Sources */, 309 | C2D67B061A7D02BB005989A2 /* AFURLResponseSerialization.m in Sources */, 310 | C2D67B071A7D02BB005989A2 /* AFURLSessionManager.m in Sources */, 311 | C2D67ABC1A7CF001005989A2 /* main.m in Sources */, 312 | ); 313 | runOnlyForDeploymentPostprocessing = 0; 314 | }; 315 | C2D67ACB1A7CF001005989A2 /* Sources */ = { 316 | isa = PBXSourcesBuildPhase; 317 | buildActionMask = 2147483647; 318 | files = ( 319 | C2D67AD61A7CF001005989A2 /* UploadExamplesTests.m in Sources */, 320 | ); 321 | runOnlyForDeploymentPostprocessing = 0; 322 | }; 323 | /* End PBXSourcesBuildPhase section */ 324 | 325 | /* Begin PBXTargetDependency section */ 326 | C2D67AD11A7CF001005989A2 /* PBXTargetDependency */ = { 327 | isa = PBXTargetDependency; 328 | target = C2D67AB51A7CF001005989A2 /* UploadExamples */; 329 | targetProxy = C2D67AD01A7CF001005989A2 /* PBXContainerItemProxy */; 330 | }; 331 | /* End PBXTargetDependency section */ 332 | 333 | /* Begin PBXVariantGroup section */ 334 | C2D67AC31A7CF001005989A2 /* Main.storyboard */ = { 335 | isa = PBXVariantGroup; 336 | children = ( 337 | C2D67AC41A7CF001005989A2 /* Base */, 338 | ); 339 | name = Main.storyboard; 340 | sourceTree = ""; 341 | }; 342 | C2D67AC81A7CF001005989A2 /* LaunchScreen.xib */ = { 343 | isa = PBXVariantGroup; 344 | children = ( 345 | C2D67AC91A7CF001005989A2 /* Base */, 346 | ); 347 | name = LaunchScreen.xib; 348 | sourceTree = ""; 349 | }; 350 | /* End PBXVariantGroup section */ 351 | 352 | /* Begin XCBuildConfiguration section */ 353 | C2D67AD71A7CF001005989A2 /* Debug */ = { 354 | isa = XCBuildConfiguration; 355 | buildSettings = { 356 | ALWAYS_SEARCH_USER_PATHS = NO; 357 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 358 | CLANG_CXX_LIBRARY = "libc++"; 359 | CLANG_ENABLE_MODULES = YES; 360 | CLANG_ENABLE_OBJC_ARC = YES; 361 | CLANG_WARN_BOOL_CONVERSION = YES; 362 | CLANG_WARN_CONSTANT_CONVERSION = YES; 363 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 364 | CLANG_WARN_EMPTY_BODY = YES; 365 | CLANG_WARN_ENUM_CONVERSION = YES; 366 | CLANG_WARN_INT_CONVERSION = YES; 367 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 368 | CLANG_WARN_UNREACHABLE_CODE = YES; 369 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 370 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 371 | COPY_PHASE_STRIP = NO; 372 | ENABLE_STRICT_OBJC_MSGSEND = YES; 373 | GCC_C_LANGUAGE_STANDARD = gnu99; 374 | GCC_DYNAMIC_NO_PIC = NO; 375 | GCC_OPTIMIZATION_LEVEL = 0; 376 | GCC_PREPROCESSOR_DEFINITIONS = ( 377 | "DEBUG=1", 378 | "$(inherited)", 379 | ); 380 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 381 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 382 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 383 | GCC_WARN_UNDECLARED_SELECTOR = YES; 384 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 385 | GCC_WARN_UNUSED_FUNCTION = YES; 386 | GCC_WARN_UNUSED_VARIABLE = YES; 387 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 388 | MTL_ENABLE_DEBUG_INFO = YES; 389 | ONLY_ACTIVE_ARCH = YES; 390 | SDKROOT = iphoneos; 391 | }; 392 | name = Debug; 393 | }; 394 | C2D67AD81A7CF001005989A2 /* Release */ = { 395 | isa = XCBuildConfiguration; 396 | buildSettings = { 397 | ALWAYS_SEARCH_USER_PATHS = NO; 398 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 399 | CLANG_CXX_LIBRARY = "libc++"; 400 | CLANG_ENABLE_MODULES = YES; 401 | CLANG_ENABLE_OBJC_ARC = YES; 402 | CLANG_WARN_BOOL_CONVERSION = YES; 403 | CLANG_WARN_CONSTANT_CONVERSION = YES; 404 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 405 | CLANG_WARN_EMPTY_BODY = YES; 406 | CLANG_WARN_ENUM_CONVERSION = YES; 407 | CLANG_WARN_INT_CONVERSION = YES; 408 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 409 | CLANG_WARN_UNREACHABLE_CODE = YES; 410 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 411 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 412 | COPY_PHASE_STRIP = YES; 413 | ENABLE_NS_ASSERTIONS = NO; 414 | ENABLE_STRICT_OBJC_MSGSEND = YES; 415 | GCC_C_LANGUAGE_STANDARD = gnu99; 416 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 417 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 418 | GCC_WARN_UNDECLARED_SELECTOR = YES; 419 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 420 | GCC_WARN_UNUSED_FUNCTION = YES; 421 | GCC_WARN_UNUSED_VARIABLE = YES; 422 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 423 | MTL_ENABLE_DEBUG_INFO = NO; 424 | SDKROOT = iphoneos; 425 | VALIDATE_PRODUCT = YES; 426 | }; 427 | name = Release; 428 | }; 429 | C2D67ADA1A7CF001005989A2 /* Debug */ = { 430 | isa = XCBuildConfiguration; 431 | buildSettings = { 432 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 433 | INFOPLIST_FILE = UploadExamples/Info.plist; 434 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 435 | PRODUCT_NAME = "$(TARGET_NAME)"; 436 | }; 437 | name = Debug; 438 | }; 439 | C2D67ADB1A7CF001005989A2 /* Release */ = { 440 | isa = XCBuildConfiguration; 441 | buildSettings = { 442 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 443 | INFOPLIST_FILE = UploadExamples/Info.plist; 444 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 445 | PRODUCT_NAME = "$(TARGET_NAME)"; 446 | }; 447 | name = Release; 448 | }; 449 | C2D67ADD1A7CF001005989A2 /* Debug */ = { 450 | isa = XCBuildConfiguration; 451 | buildSettings = { 452 | BUNDLE_LOADER = "$(TEST_HOST)"; 453 | FRAMEWORK_SEARCH_PATHS = ( 454 | "$(SDKROOT)/Developer/Library/Frameworks", 455 | "$(inherited)", 456 | ); 457 | GCC_PREPROCESSOR_DEFINITIONS = ( 458 | "DEBUG=1", 459 | "$(inherited)", 460 | ); 461 | INFOPLIST_FILE = UploadExamplesTests/Info.plist; 462 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 463 | PRODUCT_NAME = "$(TARGET_NAME)"; 464 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UploadExamples.app/UploadExamples"; 465 | }; 466 | name = Debug; 467 | }; 468 | C2D67ADE1A7CF001005989A2 /* Release */ = { 469 | isa = XCBuildConfiguration; 470 | buildSettings = { 471 | BUNDLE_LOADER = "$(TEST_HOST)"; 472 | FRAMEWORK_SEARCH_PATHS = ( 473 | "$(SDKROOT)/Developer/Library/Frameworks", 474 | "$(inherited)", 475 | ); 476 | INFOPLIST_FILE = UploadExamplesTests/Info.plist; 477 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 478 | PRODUCT_NAME = "$(TARGET_NAME)"; 479 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/UploadExamples.app/UploadExamples"; 480 | }; 481 | name = Release; 482 | }; 483 | /* End XCBuildConfiguration section */ 484 | 485 | /* Begin XCConfigurationList section */ 486 | C2D67AB11A7CF001005989A2 /* Build configuration list for PBXProject "UploadExamples" */ = { 487 | isa = XCConfigurationList; 488 | buildConfigurations = ( 489 | C2D67AD71A7CF001005989A2 /* Debug */, 490 | C2D67AD81A7CF001005989A2 /* Release */, 491 | ); 492 | defaultConfigurationIsVisible = 0; 493 | defaultConfigurationName = Release; 494 | }; 495 | C2D67AD91A7CF001005989A2 /* Build configuration list for PBXNativeTarget "UploadExamples" */ = { 496 | isa = XCConfigurationList; 497 | buildConfigurations = ( 498 | C2D67ADA1A7CF001005989A2 /* Debug */, 499 | C2D67ADB1A7CF001005989A2 /* Release */, 500 | ); 501 | defaultConfigurationIsVisible = 0; 502 | defaultConfigurationName = Release; 503 | }; 504 | C2D67ADC1A7CF001005989A2 /* Build configuration list for PBXNativeTarget "UploadExamplesTests" */ = { 505 | isa = XCConfigurationList; 506 | buildConfigurations = ( 507 | C2D67ADD1A7CF001005989A2 /* Debug */, 508 | C2D67ADE1A7CF001005989A2 /* Release */, 509 | ); 510 | defaultConfigurationIsVisible = 0; 511 | defaultConfigurationName = Release; 512 | }; 513 | /* End XCConfigurationList section */ 514 | }; 515 | rootObject = C2D67AAE1A7CF001005989A2 /* Project object */; 516 | } 517 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/111: -------------------------------------------------------------------------------- 1 | 1111111111111111 -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/222: -------------------------------------------------------------------------------- 1 | 2222222222222222 -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/AFNetworking/AFHTTPRequestOperation.h: -------------------------------------------------------------------------------- 1 | // AFHTTPRequestOperation.h 2 | // 3 | // Copyright (c) 2013-2015 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import "AFURLConnectionOperation.h" 25 | 26 | /** 27 | `AFHTTPRequestOperation` is a subclass of `AFURLConnectionOperation` for requests using the HTTP or HTTPS protocols. It encapsulates the concept of acceptable status codes and content types, which determine the success or failure of a request. 28 | */ 29 | @interface AFHTTPRequestOperation : AFURLConnectionOperation 30 | 31 | ///------------------------------------------------ 32 | /// @name Getting HTTP URL Connection Information 33 | ///------------------------------------------------ 34 | 35 | /** 36 | The last HTTP response received by the operation's connection. 37 | */ 38 | @property (readonly, nonatomic, strong) NSHTTPURLResponse *response; 39 | 40 | /** 41 | Responses sent from the server in data tasks created with `dataTaskWithRequest:success:failure:` and run using the `GET` / `POST` / et al. convenience methods are automatically validated and serialized by the response serializer. By default, this property is set to an AFHTTPResponse serializer, which uses the raw data as its response object. The serializer validates the status code to be in the `2XX` range, denoting success. If the response serializer generates an error in `-responseObjectForResponse:data:error:`, the `failure` callback of the session task or request operation will be executed; otherwise, the `success` callback will be executed. 42 | 43 | @warning `responseSerializer` must not be `nil`. Setting a response serializer will clear out any cached value 44 | */ 45 | @property (nonatomic, strong) AFHTTPResponseSerializer * responseSerializer; 46 | 47 | /** 48 | An object constructed by the `responseSerializer` from the response and response data. Returns `nil` unless the operation `isFinished`, has a `response`, and has `responseData` with non-zero content length. If an error occurs during serialization, `nil` will be returned, and the `error` property will be populated with the serialization error. 49 | */ 50 | @property (readonly, nonatomic, strong) id responseObject; 51 | 52 | ///----------------------------------------------------------- 53 | /// @name Setting Completion Block Success / Failure Callbacks 54 | ///----------------------------------------------------------- 55 | 56 | /** 57 | Sets the `completionBlock` property with a block that executes either the specified success or failure block, depending on the state of the request on completion. If `error` returns a value, which can be caused by an unacceptable status code or content type, then `failure` is executed. Otherwise, `success` is executed. 58 | 59 | This method should be overridden in subclasses in order to specify the response object passed into the success block. 60 | 61 | @param success The block to be executed on the completion of a successful request. This block has no return value and takes two arguments: the receiver operation and the object constructed from the response data of the request. 62 | @param failure The block to be executed on the completion of an unsuccessful request. This block has no return value and takes two arguments: the receiver operation and the error that occurred during the request. 63 | */ 64 | - (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success 65 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/AFNetworking/AFHTTPRequestOperation.m: -------------------------------------------------------------------------------- 1 | // AFHTTPRequestOperation.m 2 | // 3 | // Copyright (c) 2013-2015 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import "AFHTTPRequestOperation.h" 24 | 25 | static dispatch_queue_t http_request_operation_processing_queue() { 26 | static dispatch_queue_t af_http_request_operation_processing_queue; 27 | static dispatch_once_t onceToken; 28 | dispatch_once(&onceToken, ^{ 29 | af_http_request_operation_processing_queue = dispatch_queue_create("com.alamofire.networking.http-request.processing", DISPATCH_QUEUE_CONCURRENT); 30 | }); 31 | 32 | return af_http_request_operation_processing_queue; 33 | } 34 | 35 | static dispatch_group_t http_request_operation_completion_group() { 36 | static dispatch_group_t af_http_request_operation_completion_group; 37 | static dispatch_once_t onceToken; 38 | dispatch_once(&onceToken, ^{ 39 | af_http_request_operation_completion_group = dispatch_group_create(); 40 | }); 41 | 42 | return af_http_request_operation_completion_group; 43 | } 44 | 45 | #pragma mark - 46 | 47 | @interface AFURLConnectionOperation () 48 | @property (readwrite, nonatomic, strong) NSURLRequest *request; 49 | @property (readwrite, nonatomic, strong) NSURLResponse *response; 50 | @end 51 | 52 | @interface AFHTTPRequestOperation () 53 | @property (readwrite, nonatomic, strong) NSHTTPURLResponse *response; 54 | @property (readwrite, nonatomic, strong) id responseObject; 55 | @property (readwrite, nonatomic, strong) NSError *responseSerializationError; 56 | @property (readwrite, nonatomic, strong) NSRecursiveLock *lock; 57 | @end 58 | 59 | @implementation AFHTTPRequestOperation 60 | @dynamic lock; 61 | 62 | - (instancetype)initWithRequest:(NSURLRequest *)urlRequest { 63 | self = [super initWithRequest:urlRequest]; 64 | if (!self) { 65 | return nil; 66 | } 67 | 68 | self.responseSerializer = [AFHTTPResponseSerializer serializer]; 69 | 70 | return self; 71 | } 72 | 73 | - (void)setResponseSerializer:(AFHTTPResponseSerializer *)responseSerializer { 74 | NSParameterAssert(responseSerializer); 75 | 76 | [self.lock lock]; 77 | _responseSerializer = responseSerializer; 78 | self.responseObject = nil; 79 | self.responseSerializationError = nil; 80 | [self.lock unlock]; 81 | } 82 | 83 | - (id)responseObject { 84 | [self.lock lock]; 85 | if (!_responseObject && [self isFinished] && !self.error) { 86 | NSError *error = nil; 87 | self.responseObject = [self.responseSerializer responseObjectForResponse:self.response data:self.responseData error:&error]; 88 | if (error) { 89 | self.responseSerializationError = error; 90 | } 91 | } 92 | [self.lock unlock]; 93 | 94 | return _responseObject; 95 | } 96 | 97 | - (NSError *)error { 98 | if (_responseSerializationError) { 99 | return _responseSerializationError; 100 | } else { 101 | return [super error]; 102 | } 103 | } 104 | 105 | #pragma mark - AFHTTPRequestOperation 106 | 107 | - (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success 108 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure 109 | { 110 | // completionBlock is manually nilled out in AFURLConnectionOperation to break the retain cycle. 111 | #pragma clang diagnostic push 112 | #pragma clang diagnostic ignored "-Warc-retain-cycles" 113 | #pragma clang diagnostic ignored "-Wgnu" 114 | self.completionBlock = ^{ 115 | if (self.completionGroup) { 116 | dispatch_group_enter(self.completionGroup); 117 | } 118 | 119 | dispatch_async(http_request_operation_processing_queue(), ^{ 120 | if (self.error) { 121 | if (failure) { 122 | dispatch_group_async(self.completionGroup ?: http_request_operation_completion_group(), self.completionQueue ?: dispatch_get_main_queue(), ^{ 123 | failure(self, self.error); 124 | }); 125 | } 126 | } else { 127 | id responseObject = self.responseObject; 128 | if (self.error) { 129 | if (failure) { 130 | dispatch_group_async(self.completionGroup ?: http_request_operation_completion_group(), self.completionQueue ?: dispatch_get_main_queue(), ^{ 131 | failure(self, self.error); 132 | }); 133 | } 134 | } else { 135 | if (success) { 136 | dispatch_group_async(self.completionGroup ?: http_request_operation_completion_group(), self.completionQueue ?: dispatch_get_main_queue(), ^{ 137 | success(self, responseObject); 138 | }); 139 | } 140 | } 141 | } 142 | 143 | if (self.completionGroup) { 144 | dispatch_group_leave(self.completionGroup); 145 | } 146 | }); 147 | }; 148 | #pragma clang diagnostic pop 149 | } 150 | 151 | #pragma mark - AFURLRequestOperation 152 | 153 | - (void)pause { 154 | [super pause]; 155 | 156 | u_int64_t offset = 0; 157 | if ([self.outputStream propertyForKey:NSStreamFileCurrentOffsetKey]) { 158 | offset = [(NSNumber *)[self.outputStream propertyForKey:NSStreamFileCurrentOffsetKey] unsignedLongLongValue]; 159 | } else { 160 | offset = [(NSData *)[self.outputStream propertyForKey:NSStreamDataWrittenToMemoryStreamKey] length]; 161 | } 162 | 163 | NSMutableURLRequest *mutableURLRequest = [self.request mutableCopy]; 164 | if ([self.response respondsToSelector:@selector(allHeaderFields)] && [[self.response allHeaderFields] valueForKey:@"ETag"]) { 165 | [mutableURLRequest setValue:[[self.response allHeaderFields] valueForKey:@"ETag"] forHTTPHeaderField:@"If-Range"]; 166 | } 167 | [mutableURLRequest setValue:[NSString stringWithFormat:@"bytes=%llu-", offset] forHTTPHeaderField:@"Range"]; 168 | self.request = mutableURLRequest; 169 | } 170 | 171 | #pragma mark - NSSecureCoding 172 | 173 | + (BOOL)supportsSecureCoding { 174 | return YES; 175 | } 176 | 177 | - (id)initWithCoder:(NSCoder *)decoder { 178 | self = [super initWithCoder:decoder]; 179 | if (!self) { 180 | return nil; 181 | } 182 | 183 | self.responseSerializer = [decoder decodeObjectOfClass:[AFHTTPResponseSerializer class] forKey:NSStringFromSelector(@selector(responseSerializer))]; 184 | 185 | return self; 186 | } 187 | 188 | - (void)encodeWithCoder:(NSCoder *)coder { 189 | [super encodeWithCoder:coder]; 190 | 191 | [coder encodeObject:self.responseSerializer forKey:NSStringFromSelector(@selector(responseSerializer))]; 192 | } 193 | 194 | #pragma mark - NSCopying 195 | 196 | - (id)copyWithZone:(NSZone *)zone { 197 | AFHTTPRequestOperation *operation = [super copyWithZone:zone]; 198 | 199 | operation.responseSerializer = [self.responseSerializer copyWithZone:zone]; 200 | operation.completionQueue = self.completionQueue; 201 | operation.completionGroup = self.completionGroup; 202 | 203 | return operation; 204 | } 205 | 206 | @end 207 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/AFNetworking/AFHTTPRequestOperationManager.h: -------------------------------------------------------------------------------- 1 | // AFHTTPRequestOperationManager.h 2 | // 3 | // Copyright (c) 2013-2015 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import 25 | #import 26 | 27 | #if __IPHONE_OS_VERSION_MIN_REQUIRED 28 | #import 29 | #else 30 | #import 31 | #endif 32 | 33 | #import "AFHTTPRequestOperation.h" 34 | #import "AFURLResponseSerialization.h" 35 | #import "AFURLRequestSerialization.h" 36 | #import "AFSecurityPolicy.h" 37 | #import "AFNetworkReachabilityManager.h" 38 | 39 | /** 40 | `AFHTTPRequestOperationManager` encapsulates the common patterns of communicating with a web application over HTTP, including request creation, response serialization, network reachability monitoring, and security, as well as request operation management. 41 | 42 | ## Subclassing Notes 43 | 44 | Developers targeting iOS 7 or Mac OS X 10.9 or later that deal extensively with a web service are encouraged to subclass `AFHTTPSessionManager`, providing a class method that returns a shared singleton object on which authentication and other configuration can be shared across the application. 45 | 46 | For developers targeting iOS 6 or Mac OS X 10.8 or earlier, `AFHTTPRequestOperationManager` may be used to similar effect. 47 | 48 | ## Methods to Override 49 | 50 | To change the behavior of all request operation construction for an `AFHTTPRequestOperationManager` subclass, override `HTTPRequestOperationWithRequest:success:failure`. 51 | 52 | ## Serialization 53 | 54 | Requests created by an HTTP client will contain default headers and encode parameters according to the `requestSerializer` property, which is an object conforming to ``. 55 | 56 | Responses received from the server are automatically validated and serialized by the `responseSerializers` property, which is an object conforming to `` 57 | 58 | ## URL Construction Using Relative Paths 59 | 60 | For HTTP convenience methods, the request serializer constructs URLs from the path relative to the `-baseURL`, using `NSURL +URLWithString:relativeToURL:`, when provided. If `baseURL` is `nil`, `path` needs to resolve to a valid `NSURL` object using `NSURL +URLWithString:`. 61 | 62 | Below are a few examples of how `baseURL` and relative paths interact: 63 | 64 | NSURL *baseURL = [NSURL URLWithString:@"http://example.com/v1/"]; 65 | [NSURL URLWithString:@"foo" relativeToURL:baseURL]; // http://example.com/v1/foo 66 | [NSURL URLWithString:@"foo?bar=baz" relativeToURL:baseURL]; // http://example.com/v1/foo?bar=baz 67 | [NSURL URLWithString:@"/foo" relativeToURL:baseURL]; // http://example.com/foo 68 | [NSURL URLWithString:@"foo/" relativeToURL:baseURL]; // http://example.com/v1/foo 69 | [NSURL URLWithString:@"/foo/" relativeToURL:baseURL]; // http://example.com/foo/ 70 | [NSURL URLWithString:@"http://example2.com/" relativeToURL:baseURL]; // http://example2.com/ 71 | 72 | Also important to note is that a trailing slash will be added to any `baseURL` without one. This would otherwise cause unexpected behavior when constructing URLs using paths without a leading slash. 73 | 74 | ## Network Reachability Monitoring 75 | 76 | Network reachability status and change monitoring is available through the `reachabilityManager` property. Applications may choose to monitor network reachability conditions in order to prevent or suspend any outbound requests. See `AFNetworkReachabilityManager` for more details. 77 | 78 | ## NSSecureCoding & NSCopying Caveats 79 | 80 | `AFHTTPRequestOperationManager` conforms to the `NSSecureCoding` and `NSCopying` protocols, allowing operations to be archived to disk, and copied in memory, respectively. There are a few minor caveats to keep in mind, however: 81 | 82 | - Archives and copies of HTTP clients will be initialized with an empty operation queue. 83 | - NSSecureCoding cannot serialize / deserialize block properties, so an archive of an HTTP client will not include any reachability callback block that may be set. 84 | */ 85 | @interface AFHTTPRequestOperationManager : NSObject 86 | 87 | /** 88 | The URL used to monitor reachability, and construct requests from relative paths in methods like `requestWithMethod:URLString:parameters:`, and the `GET` / `POST` / et al. convenience methods. 89 | */ 90 | @property (readonly, nonatomic, strong) NSURL *baseURL; 91 | 92 | /** 93 | Requests created with `requestWithMethod:URLString:parameters:` & `multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:` are constructed with a set of default headers using a parameter serialization specified by this property. By default, this is set to an instance of `AFHTTPRequestSerializer`, which serializes query string parameters for `GET`, `HEAD`, and `DELETE` requests, or otherwise URL-form-encodes HTTP message bodies. 94 | 95 | @warning `requestSerializer` must not be `nil`. 96 | */ 97 | @property (nonatomic, strong) AFHTTPRequestSerializer * requestSerializer; 98 | 99 | /** 100 | Responses sent from the server in data tasks created with `dataTaskWithRequest:success:failure:` and run using the `GET` / `POST` / et al. convenience methods are automatically validated and serialized by the response serializer. By default, this property is set to a JSON serializer, which serializes data from responses with a `application/json` MIME type, and falls back to the raw data object. The serializer validates the status code to be in the `2XX` range, denoting success. If the response serializer generates an error in `-responseObjectForResponse:data:error:`, the `failure` callback of the session task or request operation will be executed; otherwise, the `success` callback will be executed. 101 | 102 | @warning `responseSerializer` must not be `nil`. 103 | */ 104 | @property (nonatomic, strong) AFHTTPResponseSerializer * responseSerializer; 105 | 106 | /** 107 | The operation queue on which request operations are scheduled and run. 108 | */ 109 | @property (nonatomic, strong) NSOperationQueue *operationQueue; 110 | 111 | ///------------------------------- 112 | /// @name Managing URL Credentials 113 | ///------------------------------- 114 | 115 | /** 116 | Whether request operations should consult the credential storage for authenticating the connection. `YES` by default. 117 | 118 | @see AFURLConnectionOperation -shouldUseCredentialStorage 119 | */ 120 | @property (nonatomic, assign) BOOL shouldUseCredentialStorage; 121 | 122 | /** 123 | The credential used by request operations for authentication challenges. 124 | 125 | @see AFURLConnectionOperation -credential 126 | */ 127 | @property (nonatomic, strong) NSURLCredential *credential; 128 | 129 | ///------------------------------- 130 | /// @name Managing Security Policy 131 | ///------------------------------- 132 | 133 | /** 134 | The security policy used by created request operations to evaluate server trust for secure connections. `AFHTTPRequestOperationManager` uses the `defaultPolicy` unless otherwise specified. 135 | */ 136 | @property (nonatomic, strong) AFSecurityPolicy *securityPolicy; 137 | 138 | ///------------------------------------ 139 | /// @name Managing Network Reachability 140 | ///------------------------------------ 141 | 142 | /** 143 | The network reachability manager. `AFHTTPRequestOperationManager` uses the `sharedManager` by default. 144 | */ 145 | @property (readwrite, nonatomic, strong) AFNetworkReachabilityManager *reachabilityManager; 146 | 147 | ///------------------------------- 148 | /// @name Managing Callback Queues 149 | ///------------------------------- 150 | 151 | /** 152 | The dispatch queue for the `completionBlock` of request operations. If `NULL` (default), the main queue is used. 153 | */ 154 | @property (nonatomic, strong) dispatch_queue_t completionQueue; 155 | 156 | /** 157 | The dispatch group for the `completionBlock` of request operations. If `NULL` (default), a private dispatch group is used. 158 | */ 159 | @property (nonatomic, strong) dispatch_group_t completionGroup; 160 | 161 | ///--------------------------------------------- 162 | /// @name Creating and Initializing HTTP Clients 163 | ///--------------------------------------------- 164 | 165 | /** 166 | Creates and returns an `AFHTTPRequestOperationManager` object. 167 | */ 168 | + (instancetype)manager; 169 | 170 | /** 171 | Initializes an `AFHTTPRequestOperationManager` object with the specified base URL. 172 | 173 | This is the designated initializer. 174 | 175 | @param url The base URL for the HTTP client. 176 | 177 | @return The newly-initialized HTTP client 178 | */ 179 | - (instancetype)initWithBaseURL:(NSURL *)url NS_DESIGNATED_INITIALIZER; 180 | 181 | ///--------------------------------------- 182 | /// @name Managing HTTP Request Operations 183 | ///--------------------------------------- 184 | 185 | /** 186 | Creates an `AFHTTPRequestOperation`, and sets the response serializers to that of the HTTP client. 187 | 188 | @param request The request object to be loaded asynchronously during execution of the operation. 189 | @param success A block object to be executed when the request operation finishes successfully. This block has no return value and takes two arguments: the created request operation and the object created from the response data of request. 190 | @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes two arguments:, the created request operation and the `NSError` object describing the network or parsing error that occurred. 191 | */ 192 | - (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)request 193 | success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success 194 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; 195 | 196 | ///--------------------------- 197 | /// @name Making HTTP Requests 198 | ///--------------------------- 199 | 200 | /** 201 | Creates and runs an `AFHTTPRequestOperation` with a `GET` request. 202 | 203 | @param URLString The URL string used to create the request URL. 204 | @param parameters The parameters to be encoded according to the client request serializer. 205 | @param success A block object to be executed when the request operation finishes successfully. This block has no return value and takes two arguments: the request operation, and the response object created by the client response serializer. 206 | @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the request operation and the error describing the network or parsing error that occurred. 207 | 208 | @see -HTTPRequestOperationWithRequest:success:failure: 209 | */ 210 | - (AFHTTPRequestOperation *)GET:(NSString *)URLString 211 | parameters:(id)parameters 212 | success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success 213 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; 214 | 215 | /** 216 | Creates and runs an `AFHTTPRequestOperation` with a `HEAD` request. 217 | 218 | @param URLString The URL string used to create the request URL. 219 | @param parameters The parameters to be encoded according to the client request serializer. 220 | @param success A block object to be executed when the request operation finishes successfully. This block has no return value and takes a single arguments: the request operation. 221 | @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the request operation and the error describing the network or parsing error that occurred. 222 | 223 | @see -HTTPRequestOperationWithRequest:success:failure: 224 | */ 225 | - (AFHTTPRequestOperation *)HEAD:(NSString *)URLString 226 | parameters:(id)parameters 227 | success:(void (^)(AFHTTPRequestOperation *operation))success 228 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; 229 | 230 | /** 231 | Creates and runs an `AFHTTPRequestOperation` with a `POST` request. 232 | 233 | @param URLString The URL string used to create the request URL. 234 | @param parameters The parameters to be encoded according to the client request serializer. 235 | @param success A block object to be executed when the request operation finishes successfully. This block has no return value and takes two arguments: the request operation, and the response object created by the client response serializer. 236 | @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the request operation and the error describing the network or parsing error that occurred. 237 | 238 | @see -HTTPRequestOperationWithRequest:success:failure: 239 | */ 240 | - (AFHTTPRequestOperation *)POST:(NSString *)URLString 241 | parameters:(id)parameters 242 | success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success 243 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; 244 | 245 | /** 246 | Creates and runs an `AFHTTPRequestOperation` with a multipart `POST` request. 247 | 248 | @param URLString The URL string used to create the request URL. 249 | @param parameters The parameters to be encoded according to the client request serializer. 250 | @param block A block that takes a single argument and appends data to the HTTP body. The block argument is an object adopting the `AFMultipartFormData` protocol. 251 | @param success A block object to be executed when the request operation finishes successfully. This block has no return value and takes two arguments: the request operation, and the response object created by the client response serializer. 252 | @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the request operation and the error describing the network or parsing error that occurred. 253 | 254 | @see -HTTPRequestOperationWithRequest:success:failure: 255 | */ 256 | - (AFHTTPRequestOperation *)POST:(NSString *)URLString 257 | parameters:(id)parameters 258 | constructingBodyWithBlock:(void (^)(id formData))block 259 | success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success 260 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; 261 | 262 | /** 263 | Creates and runs an `AFHTTPRequestOperation` with a `PUT` request. 264 | 265 | @param URLString The URL string used to create the request URL. 266 | @param parameters The parameters to be encoded according to the client request serializer. 267 | @param success A block object to be executed when the request operation finishes successfully. This block has no return value and takes two arguments: the request operation, and the response object created by the client response serializer. 268 | @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the request operation and the error describing the network or parsing error that occurred. 269 | 270 | @see -HTTPRequestOperationWithRequest:success:failure: 271 | */ 272 | - (AFHTTPRequestOperation *)PUT:(NSString *)URLString 273 | parameters:(id)parameters 274 | success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success 275 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; 276 | 277 | /** 278 | Creates and runs an `AFHTTPRequestOperation` with a `PATCH` request. 279 | 280 | @param URLString The URL string used to create the request URL. 281 | @param parameters The parameters to be encoded according to the client request serializer. 282 | @param success A block object to be executed when the request operation finishes successfully. This block has no return value and takes two arguments: the request operation, and the response object created by the client response serializer. 283 | @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the request operation and the error describing the network or parsing error that occurred. 284 | 285 | @see -HTTPRequestOperationWithRequest:success:failure: 286 | */ 287 | - (AFHTTPRequestOperation *)PATCH:(NSString *)URLString 288 | parameters:(id)parameters 289 | success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success 290 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; 291 | 292 | /** 293 | Creates and runs an `AFHTTPRequestOperation` with a `DELETE` request. 294 | 295 | @param URLString The URL string used to create the request URL. 296 | @param parameters The parameters to be encoded according to the client request serializer. 297 | @param success A block object to be executed when the request operation finishes successfully. This block has no return value and takes two arguments: the request operation, and the response object created by the client response serializer. 298 | @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the request operation and the error describing the network or parsing error that occurred. 299 | 300 | @see -HTTPRequestOperationWithRequest:success:failure: 301 | */ 302 | - (AFHTTPRequestOperation *)DELETE:(NSString *)URLString 303 | parameters:(id)parameters 304 | success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success 305 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure; 306 | 307 | @end 308 | 309 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/AFNetworking/AFHTTPRequestOperationManager.m: -------------------------------------------------------------------------------- 1 | // AFHTTPRequestOperationManager.m 2 | // 3 | // Copyright (c) 2013-2015 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | 25 | #import "AFHTTPRequestOperationManager.h" 26 | #import "AFHTTPRequestOperation.h" 27 | 28 | #import 29 | #import 30 | 31 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 32 | #import 33 | #endif 34 | 35 | @interface AFHTTPRequestOperationManager () 36 | @property (readwrite, nonatomic, strong) NSURL *baseURL; 37 | @end 38 | 39 | @implementation AFHTTPRequestOperationManager 40 | 41 | + (instancetype)manager { 42 | return [[self alloc] initWithBaseURL:nil]; 43 | } 44 | 45 | - (instancetype)init { 46 | return [self initWithBaseURL:nil]; 47 | } 48 | 49 | - (instancetype)initWithBaseURL:(NSURL *)url { 50 | self = [super init]; 51 | if (!self) { 52 | return nil; 53 | } 54 | 55 | // Ensure terminal slash for baseURL path, so that NSURL +URLWithString:relativeToURL: works as expected 56 | if ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) { 57 | url = [url URLByAppendingPathComponent:@""]; 58 | } 59 | 60 | self.baseURL = url; 61 | 62 | self.requestSerializer = [AFHTTPRequestSerializer serializer]; 63 | self.responseSerializer = [AFJSONResponseSerializer serializer]; 64 | 65 | self.securityPolicy = [AFSecurityPolicy defaultPolicy]; 66 | 67 | self.reachabilityManager = [AFNetworkReachabilityManager sharedManager]; 68 | 69 | self.operationQueue = [[NSOperationQueue alloc] init]; 70 | 71 | self.shouldUseCredentialStorage = YES; 72 | 73 | return self; 74 | } 75 | 76 | #pragma mark - 77 | 78 | #ifdef _SYSTEMCONFIGURATION_H 79 | #endif 80 | 81 | - (void)setRequestSerializer:(AFHTTPRequestSerializer *)requestSerializer { 82 | NSParameterAssert(requestSerializer); 83 | 84 | _requestSerializer = requestSerializer; 85 | } 86 | 87 | - (void)setResponseSerializer:(AFHTTPResponseSerializer *)responseSerializer { 88 | NSParameterAssert(responseSerializer); 89 | 90 | _responseSerializer = responseSerializer; 91 | } 92 | 93 | #pragma mark - 94 | 95 | - (AFHTTPRequestOperation *)HTTPRequestOperationWithHTTPMethod:(NSString *)method 96 | URLString:(NSString *)URLString 97 | parameters:(id)parameters 98 | success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success 99 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure 100 | { 101 | NSError *serializationError = nil; 102 | NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError]; 103 | if (serializationError) { 104 | if (failure) { 105 | #pragma clang diagnostic push 106 | #pragma clang diagnostic ignored "-Wgnu" 107 | dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ 108 | failure(nil, serializationError); 109 | }); 110 | #pragma clang diagnostic pop 111 | } 112 | 113 | return nil; 114 | } 115 | 116 | return [self HTTPRequestOperationWithRequest:request success:success failure:failure]; 117 | } 118 | 119 | - (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)request 120 | success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success 121 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure 122 | { 123 | AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; 124 | operation.responseSerializer = self.responseSerializer; 125 | operation.shouldUseCredentialStorage = self.shouldUseCredentialStorage; 126 | operation.credential = self.credential; 127 | operation.securityPolicy = self.securityPolicy; 128 | 129 | [operation setCompletionBlockWithSuccess:success failure:failure]; 130 | operation.completionQueue = self.completionQueue; 131 | operation.completionGroup = self.completionGroup; 132 | 133 | return operation; 134 | } 135 | 136 | #pragma mark - 137 | 138 | - (AFHTTPRequestOperation *)GET:(NSString *)URLString 139 | parameters:(id)parameters 140 | success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success 141 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure 142 | { 143 | AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithHTTPMethod:@"GET" URLString:URLString parameters:parameters success:success failure:failure]; 144 | 145 | [self.operationQueue addOperation:operation]; 146 | 147 | return operation; 148 | } 149 | 150 | - (AFHTTPRequestOperation *)HEAD:(NSString *)URLString 151 | parameters:(id)parameters 152 | success:(void (^)(AFHTTPRequestOperation *operation))success 153 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure 154 | { 155 | AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithHTTPMethod:@"HEAD" URLString:URLString parameters:parameters success:^(AFHTTPRequestOperation *requestOperation, __unused id responseObject) { 156 | if (success) { 157 | success(requestOperation); 158 | } 159 | } failure:failure]; 160 | 161 | [self.operationQueue addOperation:operation]; 162 | 163 | return operation; 164 | } 165 | 166 | - (AFHTTPRequestOperation *)POST:(NSString *)URLString 167 | parameters:(id)parameters 168 | success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success 169 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure 170 | { 171 | AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithHTTPMethod:@"POST" URLString:URLString parameters:parameters success:success failure:failure]; 172 | 173 | [self.operationQueue addOperation:operation]; 174 | 175 | return operation; 176 | } 177 | 178 | - (AFHTTPRequestOperation *)POST:(NSString *)URLString 179 | parameters:(id)parameters 180 | constructingBodyWithBlock:(void (^)(id formData))block 181 | success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success 182 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure 183 | { 184 | NSError *serializationError = nil; 185 | NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:&serializationError]; 186 | if (serializationError) { 187 | if (failure) { 188 | #pragma clang diagnostic push 189 | #pragma clang diagnostic ignored "-Wgnu" 190 | dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ 191 | failure(nil, serializationError); 192 | }); 193 | #pragma clang diagnostic pop 194 | } 195 | 196 | return nil; 197 | } 198 | 199 | AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure]; 200 | 201 | [self.operationQueue addOperation:operation]; 202 | 203 | return operation; 204 | } 205 | 206 | - (AFHTTPRequestOperation *)PUT:(NSString *)URLString 207 | parameters:(id)parameters 208 | success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success 209 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure 210 | { 211 | AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithHTTPMethod:@"PUT" URLString:URLString parameters:parameters success:success failure:failure]; 212 | 213 | [self.operationQueue addOperation:operation]; 214 | 215 | return operation; 216 | } 217 | 218 | - (AFHTTPRequestOperation *)PATCH:(NSString *)URLString 219 | parameters:(id)parameters 220 | success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success 221 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure 222 | { 223 | AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithHTTPMethod:@"PATCH" URLString:URLString parameters:parameters success:success failure:failure]; 224 | 225 | [self.operationQueue addOperation:operation]; 226 | 227 | return operation; 228 | } 229 | 230 | - (AFHTTPRequestOperation *)DELETE:(NSString *)URLString 231 | parameters:(id)parameters 232 | success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success 233 | failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure 234 | { 235 | AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithHTTPMethod:@"DELETE" URLString:URLString parameters:parameters success:success failure:failure]; 236 | 237 | [self.operationQueue addOperation:operation]; 238 | 239 | return operation; 240 | } 241 | 242 | #pragma mark - NSObject 243 | 244 | - (NSString *)description { 245 | return [NSString stringWithFormat:@"<%@: %p, baseURL: %@, operationQueue: %@>", NSStringFromClass([self class]), self, [self.baseURL absoluteString], self.operationQueue]; 246 | } 247 | 248 | #pragma mark - NSSecureCoding 249 | 250 | + (BOOL)supportsSecureCoding { 251 | return YES; 252 | } 253 | 254 | - (id)initWithCoder:(NSCoder *)decoder { 255 | NSURL *baseURL = [decoder decodeObjectForKey:NSStringFromSelector(@selector(baseURL))]; 256 | 257 | self = [self initWithBaseURL:baseURL]; 258 | if (!self) { 259 | return nil; 260 | } 261 | 262 | self.requestSerializer = [decoder decodeObjectOfClass:[AFHTTPRequestSerializer class] forKey:NSStringFromSelector(@selector(requestSerializer))]; 263 | self.responseSerializer = [decoder decodeObjectOfClass:[AFHTTPResponseSerializer class] forKey:NSStringFromSelector(@selector(responseSerializer))]; 264 | 265 | return self; 266 | } 267 | 268 | - (void)encodeWithCoder:(NSCoder *)coder { 269 | [coder encodeObject:self.baseURL forKey:NSStringFromSelector(@selector(baseURL))]; 270 | [coder encodeObject:self.requestSerializer forKey:NSStringFromSelector(@selector(requestSerializer))]; 271 | [coder encodeObject:self.responseSerializer forKey:NSStringFromSelector(@selector(responseSerializer))]; 272 | } 273 | 274 | #pragma mark - NSCopying 275 | 276 | - (id)copyWithZone:(NSZone *)zone { 277 | AFHTTPRequestOperationManager *HTTPClient = [[[self class] allocWithZone:zone] initWithBaseURL:self.baseURL]; 278 | 279 | HTTPClient.requestSerializer = [self.requestSerializer copyWithZone:zone]; 280 | HTTPClient.responseSerializer = [self.responseSerializer copyWithZone:zone]; 281 | 282 | return HTTPClient; 283 | } 284 | 285 | @end 286 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/AFNetworking/AFHTTPSessionManager.h: -------------------------------------------------------------------------------- 1 | // AFHTTPSessionManager.h 2 | // 3 | // Copyright (c) 2013-2015 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import 25 | #import 26 | 27 | #if __IPHONE_OS_VERSION_MIN_REQUIRED 28 | #import 29 | #else 30 | #import 31 | #endif 32 | 33 | #import "AFURLSessionManager.h" 34 | 35 | /** 36 | `AFHTTPSessionManager` is a subclass of `AFURLSessionManager` with convenience methods for making HTTP requests. When a `baseURL` is provided, requests made with the `GET` / `POST` / et al. convenience methods can be made with relative paths. 37 | 38 | ## Subclassing Notes 39 | 40 | Developers targeting iOS 7 or Mac OS X 10.9 or later that deal extensively with a web service are encouraged to subclass `AFHTTPSessionManager`, providing a class method that returns a shared singleton object on which authentication and other configuration can be shared across the application. 41 | 42 | For developers targeting iOS 6 or Mac OS X 10.8 or earlier, `AFHTTPRequestOperationManager` may be used to similar effect. 43 | 44 | ## Methods to Override 45 | 46 | To change the behavior of all data task operation construction, which is also used in the `GET` / `POST` / et al. convenience methods, override `dataTaskWithRequest:completionHandler:`. 47 | 48 | ## Serialization 49 | 50 | Requests created by an HTTP client will contain default headers and encode parameters according to the `requestSerializer` property, which is an object conforming to ``. 51 | 52 | Responses received from the server are automatically validated and serialized by the `responseSerializers` property, which is an object conforming to `` 53 | 54 | ## URL Construction Using Relative Paths 55 | 56 | For HTTP convenience methods, the request serializer constructs URLs from the path relative to the `-baseURL`, using `NSURL +URLWithString:relativeToURL:`, when provided. If `baseURL` is `nil`, `path` needs to resolve to a valid `NSURL` object using `NSURL +URLWithString:`. 57 | 58 | Below are a few examples of how `baseURL` and relative paths interact: 59 | 60 | NSURL *baseURL = [NSURL URLWithString:@"http://example.com/v1/"]; 61 | [NSURL URLWithString:@"foo" relativeToURL:baseURL]; // http://example.com/v1/foo 62 | [NSURL URLWithString:@"foo?bar=baz" relativeToURL:baseURL]; // http://example.com/v1/foo?bar=baz 63 | [NSURL URLWithString:@"/foo" relativeToURL:baseURL]; // http://example.com/foo 64 | [NSURL URLWithString:@"foo/" relativeToURL:baseURL]; // http://example.com/v1/foo 65 | [NSURL URLWithString:@"/foo/" relativeToURL:baseURL]; // http://example.com/foo/ 66 | [NSURL URLWithString:@"http://example2.com/" relativeToURL:baseURL]; // http://example2.com/ 67 | 68 | Also important to note is that a trailing slash will be added to any `baseURL` without one. This would otherwise cause unexpected behavior when constructing URLs using paths without a leading slash. 69 | 70 | @warning Managers for background sessions must be owned for the duration of their use. This can be accomplished by creating an application-wide or shared singleton instance. 71 | */ 72 | 73 | #if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090) 74 | 75 | @interface AFHTTPSessionManager : AFURLSessionManager 76 | 77 | /** 78 | The URL used to monitor reachability, and construct requests from relative paths in methods like `requestWithMethod:URLString:parameters:`, and the `GET` / `POST` / et al. convenience methods. 79 | */ 80 | @property (readonly, nonatomic, strong) NSURL *baseURL; 81 | 82 | /** 83 | Requests created with `requestWithMethod:URLString:parameters:` & `multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:` are constructed with a set of default headers using a parameter serialization specified by this property. By default, this is set to an instance of `AFHTTPRequestSerializer`, which serializes query string parameters for `GET`, `HEAD`, and `DELETE` requests, or otherwise URL-form-encodes HTTP message bodies. 84 | 85 | @warning `requestSerializer` must not be `nil`. 86 | */ 87 | @property (nonatomic, strong) AFHTTPRequestSerializer * requestSerializer; 88 | 89 | /** 90 | Responses sent from the server in data tasks created with `dataTaskWithRequest:success:failure:` and run using the `GET` / `POST` / et al. convenience methods are automatically validated and serialized by the response serializer. By default, this property is set to an instance of `AFJSONResponseSerializer`. 91 | 92 | @warning `responseSerializer` must not be `nil`. 93 | */ 94 | @property (nonatomic, strong) AFHTTPResponseSerializer * responseSerializer; 95 | 96 | ///--------------------- 97 | /// @name Initialization 98 | ///--------------------- 99 | 100 | /** 101 | Creates and returns an `AFHTTPSessionManager` object. 102 | */ 103 | + (instancetype)manager; 104 | 105 | /** 106 | Initializes an `AFHTTPSessionManager` object with the specified base URL. 107 | 108 | @param url The base URL for the HTTP client. 109 | 110 | @return The newly-initialized HTTP client 111 | */ 112 | - (instancetype)initWithBaseURL:(NSURL *)url; 113 | 114 | /** 115 | Initializes an `AFHTTPSessionManager` object with the specified base URL. 116 | 117 | This is the designated initializer. 118 | 119 | @param url The base URL for the HTTP client. 120 | @param configuration The configuration used to create the managed session. 121 | 122 | @return The newly-initialized HTTP client 123 | */ 124 | - (instancetype)initWithBaseURL:(NSURL *)url 125 | sessionConfiguration:(NSURLSessionConfiguration *)configuration NS_DESIGNATED_INITIALIZER; 126 | 127 | ///--------------------------- 128 | /// @name Making HTTP Requests 129 | ///--------------------------- 130 | 131 | /** 132 | Creates and runs an `NSURLSessionDataTask` with a `GET` request. 133 | 134 | @param URLString The URL string used to create the request URL. 135 | @param parameters The parameters to be encoded according to the client request serializer. 136 | @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. 137 | @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. 138 | 139 | @see -dataTaskWithRequest:completionHandler: 140 | */ 141 | - (NSURLSessionDataTask *)GET:(NSString *)URLString 142 | parameters:(id)parameters 143 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 144 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; 145 | 146 | /** 147 | Creates and runs an `NSURLSessionDataTask` with a `HEAD` request. 148 | 149 | @param URLString The URL string used to create the request URL. 150 | @param parameters The parameters to be encoded according to the client request serializer. 151 | @param success A block object to be executed when the task finishes successfully. This block has no return value and takes a single arguments: the data task. 152 | @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. 153 | 154 | @see -dataTaskWithRequest:completionHandler: 155 | */ 156 | - (NSURLSessionDataTask *)HEAD:(NSString *)URLString 157 | parameters:(id)parameters 158 | success:(void (^)(NSURLSessionDataTask *task))success 159 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; 160 | 161 | /** 162 | Creates and runs an `NSURLSessionDataTask` with a `POST` request. 163 | 164 | @param URLString The URL string used to create the request URL. 165 | @param parameters The parameters to be encoded according to the client request serializer. 166 | @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. 167 | @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. 168 | 169 | @see -dataTaskWithRequest:completionHandler: 170 | */ 171 | - (NSURLSessionDataTask *)POST:(NSString *)URLString 172 | parameters:(id)parameters 173 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 174 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; 175 | 176 | /** 177 | Creates and runs an `NSURLSessionDataTask` with a multipart `POST` request. 178 | 179 | @param URLString The URL string used to create the request URL. 180 | @param parameters The parameters to be encoded according to the client request serializer. 181 | @param block A block that takes a single argument and appends data to the HTTP body. The block argument is an object adopting the `AFMultipartFormData` protocol. 182 | @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. 183 | @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. 184 | 185 | @see -dataTaskWithRequest:completionHandler: 186 | */ 187 | - (NSURLSessionDataTask *)POST:(NSString *)URLString 188 | parameters:(id)parameters 189 | constructingBodyWithBlock:(void (^)(id formData))block 190 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 191 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; 192 | 193 | /** 194 | Creates and runs an `NSURLSessionDataTask` with a `PUT` request. 195 | 196 | @param URLString The URL string used to create the request URL. 197 | @param parameters The parameters to be encoded according to the client request serializer. 198 | @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. 199 | @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. 200 | 201 | @see -dataTaskWithRequest:completionHandler: 202 | */ 203 | - (NSURLSessionDataTask *)PUT:(NSString *)URLString 204 | parameters:(id)parameters 205 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 206 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; 207 | 208 | /** 209 | Creates and runs an `NSURLSessionDataTask` with a `PATCH` request. 210 | 211 | @param URLString The URL string used to create the request URL. 212 | @param parameters The parameters to be encoded according to the client request serializer. 213 | @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. 214 | @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. 215 | 216 | @see -dataTaskWithRequest:completionHandler: 217 | */ 218 | - (NSURLSessionDataTask *)PATCH:(NSString *)URLString 219 | parameters:(id)parameters 220 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 221 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; 222 | 223 | /** 224 | Creates and runs an `NSURLSessionDataTask` with a `DELETE` request. 225 | 226 | @param URLString The URL string used to create the request URL. 227 | @param parameters The parameters to be encoded according to the client request serializer. 228 | @param success A block object to be executed when the task finishes successfully. This block has no return value and takes two arguments: the data task, and the response object created by the client response serializer. 229 | @param failure A block object to be executed when the task finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a two arguments: the data task and the error describing the network or parsing error that occurred. 230 | 231 | @see -dataTaskWithRequest:completionHandler: 232 | */ 233 | - (NSURLSessionDataTask *)DELETE:(NSString *)URLString 234 | parameters:(id)parameters 235 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 236 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure; 237 | 238 | @end 239 | 240 | #endif 241 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/AFNetworking/AFHTTPSessionManager.m: -------------------------------------------------------------------------------- 1 | // AFHTTPSessionManager.m 2 | // 3 | // Copyright (c) 2013-2015 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import "AFHTTPSessionManager.h" 24 | 25 | #if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090) 26 | 27 | #import "AFURLRequestSerialization.h" 28 | #import "AFURLResponseSerialization.h" 29 | 30 | #import 31 | #import 32 | 33 | #ifdef _SYSTEMCONFIGURATION_H 34 | #import 35 | #import 36 | #import 37 | #import 38 | #import 39 | #endif 40 | 41 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 42 | #import 43 | #endif 44 | 45 | @interface AFHTTPSessionManager () 46 | @property (readwrite, nonatomic, strong) NSURL *baseURL; 47 | @end 48 | 49 | @implementation AFHTTPSessionManager 50 | 51 | + (instancetype)manager { 52 | return [[[self class] alloc] initWithBaseURL:nil]; 53 | } 54 | 55 | - (instancetype)init { 56 | return [self initWithBaseURL:nil]; 57 | } 58 | 59 | - (instancetype)initWithBaseURL:(NSURL *)url { 60 | return [self initWithBaseURL:url sessionConfiguration:nil]; 61 | } 62 | 63 | - (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration { 64 | return [self initWithBaseURL:nil sessionConfiguration:configuration]; 65 | } 66 | 67 | - (instancetype)initWithBaseURL:(NSURL *)url 68 | sessionConfiguration:(NSURLSessionConfiguration *)configuration 69 | { 70 | self = [super initWithSessionConfiguration:configuration]; 71 | if (!self) { 72 | return nil; 73 | } 74 | 75 | // Ensure terminal slash for baseURL path, so that NSURL +URLWithString:relativeToURL: works as expected 76 | if ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) { 77 | url = [url URLByAppendingPathComponent:@""]; 78 | } 79 | 80 | self.baseURL = url; 81 | 82 | self.requestSerializer = [AFHTTPRequestSerializer serializer]; 83 | self.responseSerializer = [AFJSONResponseSerializer serializer]; 84 | 85 | return self; 86 | } 87 | 88 | #pragma mark - 89 | 90 | #ifdef _SYSTEMCONFIGURATION_H 91 | #endif 92 | 93 | - (void)setRequestSerializer:(AFHTTPRequestSerializer *)requestSerializer { 94 | NSParameterAssert(requestSerializer); 95 | 96 | _requestSerializer = requestSerializer; 97 | } 98 | 99 | - (void)setResponseSerializer:(AFHTTPResponseSerializer *)responseSerializer { 100 | NSParameterAssert(responseSerializer); 101 | 102 | [super setResponseSerializer:responseSerializer]; 103 | } 104 | 105 | #pragma mark - 106 | 107 | - (NSURLSessionDataTask *)GET:(NSString *)URLString 108 | parameters:(id)parameters 109 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 110 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure 111 | { 112 | NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET" URLString:URLString parameters:parameters success:success failure:failure]; 113 | 114 | [dataTask resume]; 115 | 116 | return dataTask; 117 | } 118 | 119 | - (NSURLSessionDataTask *)HEAD:(NSString *)URLString 120 | parameters:(id)parameters 121 | success:(void (^)(NSURLSessionDataTask *task))success 122 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure 123 | { 124 | NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"HEAD" URLString:URLString parameters:parameters success:^(NSURLSessionDataTask *task, __unused id responseObject) { 125 | if (success) { 126 | success(task); 127 | } 128 | } failure:failure]; 129 | 130 | [dataTask resume]; 131 | 132 | return dataTask; 133 | } 134 | 135 | - (NSURLSessionDataTask *)POST:(NSString *)URLString 136 | parameters:(id)parameters 137 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 138 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure 139 | { 140 | NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"POST" URLString:URLString parameters:parameters success:success failure:failure]; 141 | 142 | [dataTask resume]; 143 | 144 | return dataTask; 145 | } 146 | 147 | - (NSURLSessionDataTask *)POST:(NSString *)URLString 148 | parameters:(id)parameters 149 | constructingBodyWithBlock:(void (^)(id formData))block 150 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 151 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure 152 | { 153 | NSError *serializationError = nil; 154 | NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:&serializationError]; 155 | if (serializationError) { 156 | if (failure) { 157 | #pragma clang diagnostic push 158 | #pragma clang diagnostic ignored "-Wgnu" 159 | dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ 160 | failure(nil, serializationError); 161 | }); 162 | #pragma clang diagnostic pop 163 | } 164 | 165 | return nil; 166 | } 167 | 168 | __block NSURLSessionDataTask *task = [self uploadTaskWithStreamedRequest:request progress:nil completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) { 169 | if (error) { 170 | if (failure) { 171 | failure(task, error); 172 | } 173 | } else { 174 | if (success) { 175 | success(task, responseObject); 176 | } 177 | } 178 | }]; 179 | 180 | [task resume]; 181 | 182 | return task; 183 | } 184 | 185 | - (NSURLSessionDataTask *)PUT:(NSString *)URLString 186 | parameters:(id)parameters 187 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 188 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure 189 | { 190 | NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"PUT" URLString:URLString parameters:parameters success:success failure:failure]; 191 | 192 | [dataTask resume]; 193 | 194 | return dataTask; 195 | } 196 | 197 | - (NSURLSessionDataTask *)PATCH:(NSString *)URLString 198 | parameters:(id)parameters 199 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 200 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure 201 | { 202 | NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"PATCH" URLString:URLString parameters:parameters success:success failure:failure]; 203 | 204 | [dataTask resume]; 205 | 206 | return dataTask; 207 | } 208 | 209 | - (NSURLSessionDataTask *)DELETE:(NSString *)URLString 210 | parameters:(id)parameters 211 | success:(void (^)(NSURLSessionDataTask *task, id responseObject))success 212 | failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure 213 | { 214 | NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"DELETE" URLString:URLString parameters:parameters success:success failure:failure]; 215 | 216 | [dataTask resume]; 217 | 218 | return dataTask; 219 | } 220 | 221 | - (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method 222 | URLString:(NSString *)URLString 223 | parameters:(id)parameters 224 | success:(void (^)(NSURLSessionDataTask *, id))success 225 | failure:(void (^)(NSURLSessionDataTask *, NSError *))failure 226 | { 227 | NSError *serializationError = nil; 228 | NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError]; 229 | if (serializationError) { 230 | if (failure) { 231 | #pragma clang diagnostic push 232 | #pragma clang diagnostic ignored "-Wgnu" 233 | dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{ 234 | failure(nil, serializationError); 235 | }); 236 | #pragma clang diagnostic pop 237 | } 238 | 239 | return nil; 240 | } 241 | 242 | __block NSURLSessionDataTask *dataTask = nil; 243 | dataTask = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) { 244 | if (error) { 245 | if (failure) { 246 | failure(dataTask, error); 247 | } 248 | } else { 249 | if (success) { 250 | success(dataTask, responseObject); 251 | } 252 | } 253 | }]; 254 | 255 | return dataTask; 256 | } 257 | 258 | #pragma mark - NSObject 259 | 260 | - (NSString *)description { 261 | return [NSString stringWithFormat:@"<%@: %p, baseURL: %@, session: %@, operationQueue: %@>", NSStringFromClass([self class]), self, [self.baseURL absoluteString], self.session, self.operationQueue]; 262 | } 263 | 264 | #pragma mark - NSSecureCoding 265 | 266 | + (BOOL)supportsSecureCoding { 267 | return YES; 268 | } 269 | 270 | - (id)initWithCoder:(NSCoder *)decoder { 271 | NSURL *baseURL = [decoder decodeObjectOfClass:[NSURL class] forKey:NSStringFromSelector(@selector(baseURL))]; 272 | NSURLSessionConfiguration *configuration = [decoder decodeObjectOfClass:[NSURLSessionConfiguration class] forKey:@"sessionConfiguration"]; 273 | if (!configuration) { 274 | NSString *configurationIdentifier = [decoder decodeObjectOfClass:[NSString class] forKey:@"identifier"]; 275 | if (configurationIdentifier) { 276 | #if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1100) 277 | configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:configurationIdentifier]; 278 | #else 279 | configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:configurationIdentifier]; 280 | #endif 281 | } 282 | } 283 | 284 | self = [self initWithBaseURL:baseURL sessionConfiguration:configuration]; 285 | if (!self) { 286 | return nil; 287 | } 288 | 289 | self.requestSerializer = [decoder decodeObjectOfClass:[AFHTTPRequestSerializer class] forKey:NSStringFromSelector(@selector(requestSerializer))]; 290 | self.responseSerializer = [decoder decodeObjectOfClass:[AFHTTPResponseSerializer class] forKey:NSStringFromSelector(@selector(responseSerializer))]; 291 | 292 | return self; 293 | } 294 | 295 | - (void)encodeWithCoder:(NSCoder *)coder { 296 | [super encodeWithCoder:coder]; 297 | 298 | [coder encodeObject:self.baseURL forKey:NSStringFromSelector(@selector(baseURL))]; 299 | if ([self.session.configuration conformsToProtocol:@protocol(NSCoding)]) { 300 | [coder encodeObject:self.session.configuration forKey:@"sessionConfiguration"]; 301 | } else { 302 | [coder encodeObject:self.session.configuration.identifier forKey:@"identifier"]; 303 | } 304 | [coder encodeObject:self.requestSerializer forKey:NSStringFromSelector(@selector(requestSerializer))]; 305 | [coder encodeObject:self.responseSerializer forKey:NSStringFromSelector(@selector(responseSerializer))]; 306 | } 307 | 308 | #pragma mark - NSCopying 309 | 310 | - (id)copyWithZone:(NSZone *)zone { 311 | AFHTTPSessionManager *HTTPClient = [[[self class] allocWithZone:zone] initWithBaseURL:self.baseURL sessionConfiguration:self.session.configuration]; 312 | 313 | HTTPClient.requestSerializer = [self.requestSerializer copyWithZone:zone]; 314 | HTTPClient.responseSerializer = [self.responseSerializer copyWithZone:zone]; 315 | 316 | return HTTPClient; 317 | } 318 | 319 | @end 320 | 321 | #endif 322 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/AFNetworking/AFNetworkReachabilityManager.h: -------------------------------------------------------------------------------- 1 | // AFNetworkReachabilityManager.h 2 | // 3 | // Copyright (c) 2013-2015 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import 25 | 26 | typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) { 27 | AFNetworkReachabilityStatusUnknown = -1, 28 | AFNetworkReachabilityStatusNotReachable = 0, 29 | AFNetworkReachabilityStatusReachableViaWWAN = 1, 30 | AFNetworkReachabilityStatusReachableViaWiFi = 2, 31 | }; 32 | 33 | /** 34 | `AFNetworkReachabilityManager` monitors the reachability of domains, and addresses for both WWAN and WiFi network interfaces. 35 | 36 | Reachability can be used to determine background information about why a network operation failed, or to trigger a network operation retrying when a connection is established. It should not be used to prevent a user from initiating a network request, as it's possible that an initial request may be required to establish reachability. 37 | 38 | See Apple's Reachability Sample Code (https://developer.apple.com/library/ios/samplecode/reachability/) 39 | 40 | @warning Instances of `AFNetworkReachabilityManager` must be started with `-startMonitoring` before reachability status can be determined. 41 | */ 42 | @interface AFNetworkReachabilityManager : NSObject 43 | 44 | /** 45 | The current network reachability status. 46 | */ 47 | @property (readonly, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus; 48 | 49 | /** 50 | Whether or not the network is currently reachable. 51 | */ 52 | @property (readonly, nonatomic, assign, getter = isReachable) BOOL reachable; 53 | 54 | /** 55 | Whether or not the network is currently reachable via WWAN. 56 | */ 57 | @property (readonly, nonatomic, assign, getter = isReachableViaWWAN) BOOL reachableViaWWAN; 58 | 59 | /** 60 | Whether or not the network is currently reachable via WiFi. 61 | */ 62 | @property (readonly, nonatomic, assign, getter = isReachableViaWiFi) BOOL reachableViaWiFi; 63 | 64 | ///--------------------- 65 | /// @name Initialization 66 | ///--------------------- 67 | 68 | /** 69 | Returns the shared network reachability manager. 70 | */ 71 | + (instancetype)sharedManager; 72 | 73 | /** 74 | Creates and returns a network reachability manager for the specified domain. 75 | 76 | @param domain The domain used to evaluate network reachability. 77 | 78 | @return An initialized network reachability manager, actively monitoring the specified domain. 79 | */ 80 | + (instancetype)managerForDomain:(NSString *)domain; 81 | 82 | /** 83 | Creates and returns a network reachability manager for the socket address. 84 | 85 | @param address The socket address (`sockaddr_in`) used to evaluate network reachability. 86 | 87 | @return An initialized network reachability manager, actively monitoring the specified socket address. 88 | */ 89 | + (instancetype)managerForAddress:(const void *)address; 90 | 91 | /** 92 | Initializes an instance of a network reachability manager from the specified reachability object. 93 | 94 | @param reachability The reachability object to monitor. 95 | 96 | @return An initialized network reachability manager, actively monitoring the specified reachability. 97 | */ 98 | - (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability NS_DESIGNATED_INITIALIZER; 99 | 100 | ///-------------------------------------------------- 101 | /// @name Starting & Stopping Reachability Monitoring 102 | ///-------------------------------------------------- 103 | 104 | /** 105 | Starts monitoring for changes in network reachability status. 106 | */ 107 | - (void)startMonitoring; 108 | 109 | /** 110 | Stops monitoring for changes in network reachability status. 111 | */ 112 | - (void)stopMonitoring; 113 | 114 | ///------------------------------------------------- 115 | /// @name Getting Localized Reachability Description 116 | ///------------------------------------------------- 117 | 118 | /** 119 | Returns a localized string representation of the current network reachability status. 120 | */ 121 | - (NSString *)localizedNetworkReachabilityStatusString; 122 | 123 | ///--------------------------------------------------- 124 | /// @name Setting Network Reachability Change Callback 125 | ///--------------------------------------------------- 126 | 127 | /** 128 | Sets a callback to be executed when the network availability of the `baseURL` host changes. 129 | 130 | @param block A block object to be executed when the network availability of the `baseURL` host changes.. This block has no return value and takes a single argument which represents the various reachability states from the device to the `baseURL`. 131 | */ 132 | - (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus status))block; 133 | 134 | @end 135 | 136 | ///---------------- 137 | /// @name Constants 138 | ///---------------- 139 | 140 | /** 141 | ## Network Reachability 142 | 143 | The following constants are provided by `AFNetworkReachabilityManager` as possible network reachability statuses. 144 | 145 | enum { 146 | AFNetworkReachabilityStatusUnknown, 147 | AFNetworkReachabilityStatusNotReachable, 148 | AFNetworkReachabilityStatusReachableViaWWAN, 149 | AFNetworkReachabilityStatusReachableViaWiFi, 150 | } 151 | 152 | `AFNetworkReachabilityStatusUnknown` 153 | The `baseURL` host reachability is not known. 154 | 155 | `AFNetworkReachabilityStatusNotReachable` 156 | The `baseURL` host cannot be reached. 157 | 158 | `AFNetworkReachabilityStatusReachableViaWWAN` 159 | The `baseURL` host can be reached via a cellular connection, such as EDGE or GPRS. 160 | 161 | `AFNetworkReachabilityStatusReachableViaWiFi` 162 | The `baseURL` host can be reached via a Wi-Fi connection. 163 | 164 | ### Keys for Notification UserInfo Dictionary 165 | 166 | Strings that are used as keys in a `userInfo` dictionary in a network reachability status change notification. 167 | 168 | `AFNetworkingReachabilityNotificationStatusItem` 169 | A key in the userInfo dictionary in a `AFNetworkingReachabilityDidChangeNotification` notification. 170 | The corresponding value is an `NSNumber` object representing the `AFNetworkReachabilityStatus` value for the current reachability status. 171 | */ 172 | 173 | ///-------------------- 174 | /// @name Notifications 175 | ///-------------------- 176 | 177 | /** 178 | Posted when network reachability changes. 179 | This notification assigns no notification object. The `userInfo` dictionary contains an `NSNumber` object under the `AFNetworkingReachabilityNotificationStatusItem` key, representing the `AFNetworkReachabilityStatus` value for the current network reachability. 180 | 181 | @warning In order for network reachability to be monitored, include the `SystemConfiguration` framework in the active target's "Link Binary With Library" build phase, and add `#import ` to the header prefix of the project (`Prefix.pch`). 182 | */ 183 | extern NSString * const AFNetworkingReachabilityDidChangeNotification; 184 | extern NSString * const AFNetworkingReachabilityNotificationStatusItem; 185 | 186 | ///-------------------- 187 | /// @name Functions 188 | ///-------------------- 189 | 190 | /** 191 | Returns a localized string representation of an `AFNetworkReachabilityStatus` value. 192 | */ 193 | extern NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status); 194 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/AFNetworking/AFNetworkReachabilityManager.m: -------------------------------------------------------------------------------- 1 | // AFNetworkReachabilityManager.m 2 | // 3 | // Copyright (c) 2013-2015 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import "AFNetworkReachabilityManager.h" 24 | 25 | #import 26 | #import 27 | #import 28 | #import 29 | #import 30 | 31 | NSString * const AFNetworkingReachabilityDidChangeNotification = @"com.alamofire.networking.reachability.change"; 32 | NSString * const AFNetworkingReachabilityNotificationStatusItem = @"AFNetworkingReachabilityNotificationStatusItem"; 33 | 34 | typedef void (^AFNetworkReachabilityStatusBlock)(AFNetworkReachabilityStatus status); 35 | 36 | typedef NS_ENUM(NSUInteger, AFNetworkReachabilityAssociation) { 37 | AFNetworkReachabilityForAddress = 1, 38 | AFNetworkReachabilityForAddressPair = 2, 39 | AFNetworkReachabilityForName = 3, 40 | }; 41 | 42 | NSString * AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status) { 43 | switch (status) { 44 | case AFNetworkReachabilityStatusNotReachable: 45 | return NSLocalizedStringFromTable(@"Not Reachable", @"AFNetworking", nil); 46 | case AFNetworkReachabilityStatusReachableViaWWAN: 47 | return NSLocalizedStringFromTable(@"Reachable via WWAN", @"AFNetworking", nil); 48 | case AFNetworkReachabilityStatusReachableViaWiFi: 49 | return NSLocalizedStringFromTable(@"Reachable via WiFi", @"AFNetworking", nil); 50 | case AFNetworkReachabilityStatusUnknown: 51 | default: 52 | return NSLocalizedStringFromTable(@"Unknown", @"AFNetworking", nil); 53 | } 54 | } 55 | 56 | static AFNetworkReachabilityStatus AFNetworkReachabilityStatusForFlags(SCNetworkReachabilityFlags flags) { 57 | BOOL isReachable = ((flags & kSCNetworkReachabilityFlagsReachable) != 0); 58 | BOOL needsConnection = ((flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0); 59 | BOOL canConnectionAutomatically = (((flags & kSCNetworkReachabilityFlagsConnectionOnDemand ) != 0) || ((flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)); 60 | BOOL canConnectWithoutUserInteraction = (canConnectionAutomatically && (flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0); 61 | BOOL isNetworkReachable = (isReachable && (!needsConnection || canConnectWithoutUserInteraction)); 62 | 63 | AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusUnknown; 64 | if (isNetworkReachable == NO) { 65 | status = AFNetworkReachabilityStatusNotReachable; 66 | } 67 | #if TARGET_OS_IPHONE 68 | else if ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0) { 69 | status = AFNetworkReachabilityStatusReachableViaWWAN; 70 | } 71 | #endif 72 | else { 73 | status = AFNetworkReachabilityStatusReachableViaWiFi; 74 | } 75 | 76 | return status; 77 | } 78 | 79 | static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) { 80 | AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags); 81 | AFNetworkReachabilityStatusBlock block = (__bridge AFNetworkReachabilityStatusBlock)info; 82 | if (block) { 83 | block(status); 84 | } 85 | 86 | 87 | dispatch_async(dispatch_get_main_queue(), ^{ 88 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 89 | [notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:@{ AFNetworkingReachabilityNotificationStatusItem: @(status) }]; 90 | }); 91 | 92 | } 93 | 94 | static const void * AFNetworkReachabilityRetainCallback(const void *info) { 95 | return Block_copy(info); 96 | } 97 | 98 | static void AFNetworkReachabilityReleaseCallback(const void *info) { 99 | if (info) { 100 | Block_release(info); 101 | } 102 | } 103 | 104 | @interface AFNetworkReachabilityManager () 105 | @property (readwrite, nonatomic, assign) SCNetworkReachabilityRef networkReachability; 106 | @property (readwrite, nonatomic, assign) AFNetworkReachabilityAssociation networkReachabilityAssociation; 107 | @property (readwrite, nonatomic, assign) AFNetworkReachabilityStatus networkReachabilityStatus; 108 | @property (readwrite, nonatomic, copy) AFNetworkReachabilityStatusBlock networkReachabilityStatusBlock; 109 | @end 110 | 111 | @implementation AFNetworkReachabilityManager 112 | 113 | + (instancetype)sharedManager { 114 | static AFNetworkReachabilityManager *_sharedManager = nil; 115 | static dispatch_once_t onceToken; 116 | dispatch_once(&onceToken, ^{ 117 | struct sockaddr_in address; 118 | bzero(&address, sizeof(address)); 119 | address.sin_len = sizeof(address); 120 | address.sin_family = AF_INET; 121 | 122 | _sharedManager = [self managerForAddress:&address]; 123 | }); 124 | 125 | return _sharedManager; 126 | } 127 | 128 | + (instancetype)managerForDomain:(NSString *)domain { 129 | SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, [domain UTF8String]); 130 | 131 | AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability]; 132 | manager.networkReachabilityAssociation = AFNetworkReachabilityForName; 133 | 134 | return manager; 135 | } 136 | 137 | + (instancetype)managerForAddress:(const void *)address { 138 | SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)address); 139 | 140 | AFNetworkReachabilityManager *manager = [[self alloc] initWithReachability:reachability]; 141 | manager.networkReachabilityAssociation = AFNetworkReachabilityForAddress; 142 | 143 | return manager; 144 | } 145 | 146 | - (instancetype)initWithReachability:(SCNetworkReachabilityRef)reachability { 147 | self = [super init]; 148 | if (!self) { 149 | return nil; 150 | } 151 | 152 | self.networkReachability = reachability; 153 | self.networkReachabilityStatus = AFNetworkReachabilityStatusUnknown; 154 | 155 | return self; 156 | } 157 | 158 | - (void)dealloc { 159 | [self stopMonitoring]; 160 | 161 | if (_networkReachability) { 162 | CFRelease(_networkReachability); 163 | _networkReachability = NULL; 164 | } 165 | } 166 | 167 | #pragma mark - 168 | 169 | - (BOOL)isReachable { 170 | return [self isReachableViaWWAN] || [self isReachableViaWiFi]; 171 | } 172 | 173 | - (BOOL)isReachableViaWWAN { 174 | return self.networkReachabilityStatus == AFNetworkReachabilityStatusReachableViaWWAN; 175 | } 176 | 177 | - (BOOL)isReachableViaWiFi { 178 | return self.networkReachabilityStatus == AFNetworkReachabilityStatusReachableViaWiFi; 179 | } 180 | 181 | #pragma mark - 182 | 183 | - (void)startMonitoring { 184 | [self stopMonitoring]; 185 | 186 | if (!self.networkReachability) { 187 | return; 188 | } 189 | 190 | __weak __typeof(self)weakSelf = self; 191 | AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) { 192 | __strong __typeof(weakSelf)strongSelf = weakSelf; 193 | 194 | strongSelf.networkReachabilityStatus = status; 195 | if (strongSelf.networkReachabilityStatusBlock) { 196 | strongSelf.networkReachabilityStatusBlock(status); 197 | } 198 | 199 | }; 200 | 201 | SCNetworkReachabilityContext context = {0, (__bridge void *)callback, AFNetworkReachabilityRetainCallback, AFNetworkReachabilityReleaseCallback, NULL}; 202 | SCNetworkReachabilitySetCallback(self.networkReachability, AFNetworkReachabilityCallback, &context); 203 | SCNetworkReachabilityScheduleWithRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); 204 | 205 | switch (self.networkReachabilityAssociation) { 206 | case AFNetworkReachabilityForName: 207 | break; 208 | case AFNetworkReachabilityForAddress: 209 | case AFNetworkReachabilityForAddressPair: 210 | default: { 211 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),^{ 212 | SCNetworkReachabilityFlags flags; 213 | SCNetworkReachabilityGetFlags(self.networkReachability, &flags); 214 | AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags); 215 | dispatch_async(dispatch_get_main_queue(), ^{ 216 | callback(status); 217 | 218 | NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; 219 | [notificationCenter postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:@{ AFNetworkingReachabilityNotificationStatusItem: @(status) }]; 220 | 221 | 222 | }); 223 | }); 224 | } 225 | break; 226 | } 227 | } 228 | 229 | - (void)stopMonitoring { 230 | if (!self.networkReachability) { 231 | return; 232 | } 233 | 234 | SCNetworkReachabilityUnscheduleFromRunLoop(self.networkReachability, CFRunLoopGetMain(), kCFRunLoopCommonModes); 235 | } 236 | 237 | #pragma mark - 238 | 239 | - (NSString *)localizedNetworkReachabilityStatusString { 240 | return AFStringFromNetworkReachabilityStatus(self.networkReachabilityStatus); 241 | } 242 | 243 | #pragma mark - 244 | 245 | - (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus status))block { 246 | self.networkReachabilityStatusBlock = block; 247 | } 248 | 249 | #pragma mark - NSKeyValueObserving 250 | 251 | + (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key { 252 | if ([key isEqualToString:@"reachable"] || [key isEqualToString:@"reachableViaWWAN"] || [key isEqualToString:@"reachableViaWiFi"]) { 253 | return [NSSet setWithObject:@"networkReachabilityStatus"]; 254 | } 255 | 256 | return [super keyPathsForValuesAffectingValueForKey:key]; 257 | } 258 | 259 | @end 260 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/AFNetworking/AFNetworking.h: -------------------------------------------------------------------------------- 1 | // AFNetworking.h 2 | // 3 | // Copyright (c) 2013 AFNetworking (http://afnetworking.com/) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import 25 | 26 | #ifndef _AFNETWORKING_ 27 | #define _AFNETWORKING_ 28 | 29 | #import "AFURLRequestSerialization.h" 30 | #import "AFURLResponseSerialization.h" 31 | #import "AFSecurityPolicy.h" 32 | #import "AFNetworkReachabilityManager.h" 33 | 34 | #import "AFURLConnectionOperation.h" 35 | #import "AFHTTPRequestOperation.h" 36 | #import "AFHTTPRequestOperationManager.h" 37 | 38 | #if ( ( defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090) || \ 39 | ( defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 ) ) 40 | #import "AFURLSessionManager.h" 41 | #import "AFHTTPSessionManager.h" 42 | #endif 43 | 44 | #endif /* _AFNETWORKING_ */ 45 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/AFNetworking/AFSecurityPolicy.h: -------------------------------------------------------------------------------- 1 | // AFSecurityPolicy.h 2 | // 3 | // Copyright (c) 2013-2015 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import 25 | 26 | typedef NS_ENUM(NSUInteger, AFSSLPinningMode) { 27 | AFSSLPinningModeNone, 28 | AFSSLPinningModePublicKey, 29 | AFSSLPinningModeCertificate, 30 | }; 31 | 32 | /** 33 | `AFSecurityPolicy` evaluates server trust against pinned X.509 certificates and public keys over secure connections. 34 | 35 | Adding pinned SSL certificates to your app helps prevent man-in-the-middle attacks and other vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged to route all communication over an HTTPS connection with SSL pinning configured and enabled. 36 | */ 37 | @interface AFSecurityPolicy : NSObject 38 | 39 | /** 40 | The criteria by which server trust should be evaluated against the pinned SSL certificates. Defaults to `AFSSLPinningModeNone`. 41 | */ 42 | @property (readonly, nonatomic, assign) AFSSLPinningMode SSLPinningMode; 43 | 44 | /** 45 | Whether to evaluate an entire SSL certificate chain, or just the leaf certificate. Defaults to `YES`. 46 | */ 47 | @property (nonatomic, assign) BOOL validatesCertificateChain; 48 | 49 | /** 50 | The certificates used to evaluate server trust according to the SSL pinning mode. By default, this property is set to any (`.cer`) certificates included in the app bundle. 51 | */ 52 | @property (nonatomic, strong) NSArray *pinnedCertificates; 53 | 54 | /** 55 | Whether or not to trust servers with an invalid or expired SSL certificates. Defaults to `NO`. 56 | */ 57 | @property (nonatomic, assign) BOOL allowInvalidCertificates; 58 | 59 | /** 60 | Whether or not to validate the domain name in the certificate's CN field. Defaults to `YES` for `AFSSLPinningModePublicKey` or `AFSSLPinningModeCertificate`, otherwise `NO`. 61 | */ 62 | @property (nonatomic, assign) BOOL validatesDomainName; 63 | 64 | ///----------------------------------------- 65 | /// @name Getting Specific Security Policies 66 | ///----------------------------------------- 67 | 68 | /** 69 | Returns the shared default security policy, which does not allow invalid certificates, does not validate domain name, and does not validate against pinned certificates or public keys. 70 | 71 | @return The default security policy. 72 | */ 73 | + (instancetype)defaultPolicy; 74 | 75 | ///--------------------- 76 | /// @name Initialization 77 | ///--------------------- 78 | 79 | /** 80 | Creates and returns a security policy with the specified pinning mode. 81 | 82 | @param pinningMode The SSL pinning mode. 83 | 84 | @return A new security policy. 85 | */ 86 | + (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode; 87 | 88 | ///------------------------------ 89 | /// @name Evaluating Server Trust 90 | ///------------------------------ 91 | 92 | /** 93 | Whether or not the specified server trust should be accepted, based on the security policy. 94 | 95 | This method should be used when responding to an authentication challenge from a server. 96 | 97 | @param serverTrust The X.509 certificate trust of the server. 98 | 99 | @return Whether or not to trust the server. 100 | 101 | @warning This method has been deprecated in favor of `-evaluateServerTrust:forDomain:`. 102 | */ 103 | - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust DEPRECATED_ATTRIBUTE; 104 | 105 | /** 106 | Whether or not the specified server trust should be accepted, based on the security policy. 107 | 108 | This method should be used when responding to an authentication challenge from a server. 109 | 110 | @param serverTrust The X.509 certificate trust of the server. 111 | @param domain The domain of serverTrust. If `nil`, the domain will not be validated. 112 | 113 | @return Whether or not to trust the server. 114 | */ 115 | - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust 116 | forDomain:(NSString *)domain; 117 | 118 | @end 119 | 120 | ///---------------- 121 | /// @name Constants 122 | ///---------------- 123 | 124 | /** 125 | ## SSL Pinning Modes 126 | 127 | The following constants are provided by `AFSSLPinningMode` as possible SSL pinning modes. 128 | 129 | enum { 130 | AFSSLPinningModeNone, 131 | AFSSLPinningModePublicKey, 132 | AFSSLPinningModeCertificate, 133 | } 134 | 135 | `AFSSLPinningModeNone` 136 | Do not used pinned certificates to validate servers. 137 | 138 | `AFSSLPinningModePublicKey` 139 | Validate host certificates against public keys of pinned certificates. 140 | 141 | `AFSSLPinningModeCertificate` 142 | Validate host certificates against pinned certificates. 143 | */ 144 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/AFNetworking/AFSecurityPolicy.m: -------------------------------------------------------------------------------- 1 | // AFSecurityPolicy.m 2 | // 3 | // Copyright (c) 2013-2015 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import "AFSecurityPolicy.h" 24 | 25 | #import 26 | 27 | #if !defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 28 | static NSData * AFSecKeyGetData(SecKeyRef key) { 29 | CFDataRef data = NULL; 30 | 31 | __Require_noErr_Quiet(SecItemExport(key, kSecFormatUnknown, kSecItemPemArmour, NULL, &data), _out); 32 | 33 | return (__bridge_transfer NSData *)data; 34 | 35 | _out: 36 | if (data) { 37 | CFRelease(data); 38 | } 39 | 40 | return nil; 41 | } 42 | #endif 43 | 44 | static BOOL AFSecKeyIsEqualToKey(SecKeyRef key1, SecKeyRef key2) { 45 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 46 | return [(__bridge id)key1 isEqual:(__bridge id)key2]; 47 | #else 48 | return [AFSecKeyGetData(key1) isEqual:AFSecKeyGetData(key2)]; 49 | #endif 50 | } 51 | 52 | static id AFPublicKeyForCertificate(NSData *certificate) { 53 | id allowedPublicKey = nil; 54 | SecCertificateRef allowedCertificate; 55 | SecCertificateRef allowedCertificates[1]; 56 | CFArrayRef tempCertificates = nil; 57 | SecPolicyRef policy = nil; 58 | SecTrustRef allowedTrust = nil; 59 | SecTrustResultType result; 60 | 61 | allowedCertificate = SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificate); 62 | __Require_Quiet(allowedCertificate != NULL, _out); 63 | 64 | allowedCertificates[0] = allowedCertificate; 65 | tempCertificates = CFArrayCreate(NULL, (const void **)allowedCertificates, 1, NULL); 66 | 67 | policy = SecPolicyCreateBasicX509(); 68 | __Require_noErr_Quiet(SecTrustCreateWithCertificates(tempCertificates, policy, &allowedTrust), _out); 69 | __Require_noErr_Quiet(SecTrustEvaluate(allowedTrust, &result), _out); 70 | 71 | allowedPublicKey = (__bridge_transfer id)SecTrustCopyPublicKey(allowedTrust); 72 | 73 | _out: 74 | if (allowedTrust) { 75 | CFRelease(allowedTrust); 76 | } 77 | 78 | if (policy) { 79 | CFRelease(policy); 80 | } 81 | 82 | if (tempCertificates) { 83 | CFRelease(tempCertificates); 84 | } 85 | 86 | if (allowedCertificate) { 87 | CFRelease(allowedCertificate); 88 | } 89 | 90 | return allowedPublicKey; 91 | } 92 | 93 | static BOOL AFServerTrustIsValid(SecTrustRef serverTrust) { 94 | BOOL isValid = NO; 95 | SecTrustResultType result; 96 | __Require_noErr_Quiet(SecTrustEvaluate(serverTrust, &result), _out); 97 | 98 | isValid = (result == kSecTrustResultUnspecified || result == kSecTrustResultProceed); 99 | 100 | _out: 101 | return isValid; 102 | } 103 | 104 | static NSArray * AFCertificateTrustChainForServerTrust(SecTrustRef serverTrust) { 105 | CFIndex certificateCount = SecTrustGetCertificateCount(serverTrust); 106 | NSMutableArray *trustChain = [NSMutableArray arrayWithCapacity:(NSUInteger)certificateCount]; 107 | 108 | for (CFIndex i = 0; i < certificateCount; i++) { 109 | SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i); 110 | [trustChain addObject:(__bridge_transfer NSData *)SecCertificateCopyData(certificate)]; 111 | } 112 | 113 | return [NSArray arrayWithArray:trustChain]; 114 | } 115 | 116 | static NSArray * AFPublicKeyTrustChainForServerTrust(SecTrustRef serverTrust) { 117 | SecPolicyRef policy = SecPolicyCreateBasicX509(); 118 | CFIndex certificateCount = SecTrustGetCertificateCount(serverTrust); 119 | NSMutableArray *trustChain = [NSMutableArray arrayWithCapacity:(NSUInteger)certificateCount]; 120 | for (CFIndex i = 0; i < certificateCount; i++) { 121 | SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, i); 122 | 123 | SecCertificateRef someCertificates[] = {certificate}; 124 | CFArrayRef certificates = CFArrayCreate(NULL, (const void **)someCertificates, 1, NULL); 125 | 126 | SecTrustRef trust; 127 | __Require_noErr_Quiet(SecTrustCreateWithCertificates(certificates, policy, &trust), _out); 128 | 129 | SecTrustResultType result; 130 | __Require_noErr_Quiet(SecTrustEvaluate(trust, &result), _out); 131 | 132 | [trustChain addObject:(__bridge_transfer id)SecTrustCopyPublicKey(trust)]; 133 | 134 | _out: 135 | if (trust) { 136 | CFRelease(trust); 137 | } 138 | 139 | if (certificates) { 140 | CFRelease(certificates); 141 | } 142 | 143 | continue; 144 | } 145 | CFRelease(policy); 146 | 147 | return [NSArray arrayWithArray:trustChain]; 148 | } 149 | 150 | #pragma mark - 151 | 152 | @interface AFSecurityPolicy() 153 | @property (readwrite, nonatomic, assign) AFSSLPinningMode SSLPinningMode; 154 | @property (readwrite, nonatomic, strong) NSArray *pinnedPublicKeys; 155 | @end 156 | 157 | @implementation AFSecurityPolicy 158 | 159 | + (NSArray *)defaultPinnedCertificates { 160 | static NSArray *_defaultPinnedCertificates = nil; 161 | static dispatch_once_t onceToken; 162 | dispatch_once(&onceToken, ^{ 163 | NSBundle *bundle = [NSBundle bundleForClass:[self class]]; 164 | NSArray *paths = [bundle pathsForResourcesOfType:@"cer" inDirectory:@"."]; 165 | 166 | NSMutableArray *certificates = [NSMutableArray arrayWithCapacity:[paths count]]; 167 | for (NSString *path in paths) { 168 | NSData *certificateData = [NSData dataWithContentsOfFile:path]; 169 | [certificates addObject:certificateData]; 170 | } 171 | 172 | _defaultPinnedCertificates = [[NSArray alloc] initWithArray:certificates]; 173 | }); 174 | 175 | return _defaultPinnedCertificates; 176 | } 177 | 178 | + (instancetype)defaultPolicy { 179 | AFSecurityPolicy *securityPolicy = [[self alloc] init]; 180 | securityPolicy.SSLPinningMode = AFSSLPinningModeNone; 181 | 182 | return securityPolicy; 183 | } 184 | 185 | + (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode { 186 | AFSecurityPolicy *securityPolicy = [[self alloc] init]; 187 | securityPolicy.SSLPinningMode = pinningMode; 188 | 189 | [securityPolicy setPinnedCertificates:[self defaultPinnedCertificates]]; 190 | 191 | return securityPolicy; 192 | } 193 | 194 | - (id)init { 195 | self = [super init]; 196 | if (!self) { 197 | return nil; 198 | } 199 | 200 | self.validatesCertificateChain = YES; 201 | 202 | return self; 203 | } 204 | 205 | #pragma mark - 206 | 207 | - (void)setSSLPinningMode:(AFSSLPinningMode)SSLPinningMode { 208 | _SSLPinningMode = SSLPinningMode; 209 | 210 | switch (self.SSLPinningMode) { 211 | case AFSSLPinningModePublicKey: 212 | case AFSSLPinningModeCertificate: 213 | self.validatesDomainName = YES; 214 | break; 215 | default: 216 | self.validatesDomainName = NO; 217 | break; 218 | } 219 | } 220 | 221 | - (void)setPinnedCertificates:(NSArray *)pinnedCertificates { 222 | _pinnedCertificates = pinnedCertificates; 223 | 224 | if (self.pinnedCertificates) { 225 | NSMutableArray *mutablePinnedPublicKeys = [NSMutableArray arrayWithCapacity:[self.pinnedCertificates count]]; 226 | for (NSData *certificate in self.pinnedCertificates) { 227 | id publicKey = AFPublicKeyForCertificate(certificate); 228 | if (!publicKey) { 229 | continue; 230 | } 231 | [mutablePinnedPublicKeys addObject:publicKey]; 232 | } 233 | self.pinnedPublicKeys = [NSArray arrayWithArray:mutablePinnedPublicKeys]; 234 | } else { 235 | self.pinnedPublicKeys = nil; 236 | } 237 | } 238 | 239 | #pragma mark - 240 | 241 | - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust { 242 | return [self evaluateServerTrust:serverTrust forDomain:nil]; 243 | } 244 | 245 | - (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust 246 | forDomain:(NSString *)domain 247 | { 248 | NSMutableArray *policies = [NSMutableArray array]; 249 | if (self.validatesDomainName) { 250 | [policies addObject:(__bridge_transfer id)SecPolicyCreateSSL(true, (__bridge CFStringRef)domain)]; 251 | } else { 252 | [policies addObject:(__bridge_transfer id)SecPolicyCreateBasicX509()]; 253 | } 254 | 255 | SecTrustSetPolicies(serverTrust, (__bridge CFArrayRef)policies); 256 | 257 | if (self.SSLPinningMode != AFSSLPinningModeNone && !AFServerTrustIsValid(serverTrust) && !self.allowInvalidCertificates) { 258 | return NO; 259 | } 260 | 261 | NSArray *serverCertificates = AFCertificateTrustChainForServerTrust(serverTrust); 262 | switch (self.SSLPinningMode) { 263 | case AFSSLPinningModeNone: 264 | return YES; 265 | case AFSSLPinningModeCertificate: { 266 | NSMutableArray *pinnedCertificates = [NSMutableArray array]; 267 | for (NSData *certificateData in self.pinnedCertificates) { 268 | [pinnedCertificates addObject:(__bridge_transfer id)SecCertificateCreateWithData(NULL, (__bridge CFDataRef)certificateData)]; 269 | } 270 | SecTrustSetAnchorCertificates(serverTrust, (__bridge CFArrayRef)pinnedCertificates); 271 | 272 | if (!AFServerTrustIsValid(serverTrust)) { 273 | return NO; 274 | } 275 | 276 | if (!self.validatesCertificateChain) { 277 | return YES; 278 | } 279 | 280 | NSUInteger trustedCertificateCount = 0; 281 | for (NSData *trustChainCertificate in serverCertificates) { 282 | if ([self.pinnedCertificates containsObject:trustChainCertificate]) { 283 | trustedCertificateCount++; 284 | } 285 | } 286 | 287 | return trustedCertificateCount == [serverCertificates count]; 288 | } 289 | case AFSSLPinningModePublicKey: { 290 | NSUInteger trustedPublicKeyCount = 0; 291 | NSArray *publicKeys = AFPublicKeyTrustChainForServerTrust(serverTrust); 292 | if (!self.validatesCertificateChain && [publicKeys count] > 0) { 293 | publicKeys = @[[publicKeys firstObject]]; 294 | } 295 | 296 | for (id trustChainPublicKey in publicKeys) { 297 | for (id pinnedPublicKey in self.pinnedPublicKeys) { 298 | if (AFSecKeyIsEqualToKey((__bridge SecKeyRef)trustChainPublicKey, (__bridge SecKeyRef)pinnedPublicKey)) { 299 | trustedPublicKeyCount += 1; 300 | } 301 | } 302 | } 303 | 304 | return trustedPublicKeyCount > 0 && ((self.validatesCertificateChain && trustedPublicKeyCount == [serverCertificates count]) || (!self.validatesCertificateChain && trustedPublicKeyCount >= 1)); 305 | } 306 | } 307 | 308 | return NO; 309 | } 310 | 311 | #pragma mark - NSKeyValueObserving 312 | 313 | + (NSSet *)keyPathsForValuesAffectingPinnedPublicKeys { 314 | return [NSSet setWithObject:@"pinnedCertificates"]; 315 | } 316 | 317 | @end 318 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/AFNetworking/AFURLConnectionOperation.h: -------------------------------------------------------------------------------- 1 | // AFURLConnectionOperation.h 2 | // 3 | // Copyright (c) 2013-2015 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | 25 | #import 26 | #import "AFURLRequestSerialization.h" 27 | #import "AFURLResponseSerialization.h" 28 | #import "AFSecurityPolicy.h" 29 | 30 | /** 31 | `AFURLConnectionOperation` is a subclass of `NSOperation` that implements `NSURLConnection` delegate methods. 32 | 33 | ## Subclassing Notes 34 | 35 | This is the base class of all network request operations. You may wish to create your own subclass in order to implement additional `NSURLConnection` delegate methods (see "`NSURLConnection` Delegate Methods" below), or to provide additional properties and/or class constructors. 36 | 37 | If you are creating a subclass that communicates over the HTTP or HTTPS protocols, you may want to consider subclassing `AFHTTPRequestOperation` instead, as it supports specifying acceptable content types or status codes. 38 | 39 | ## NSURLConnection Delegate Methods 40 | 41 | `AFURLConnectionOperation` implements the following `NSURLConnection` delegate methods: 42 | 43 | - `connection:didReceiveResponse:` 44 | - `connection:didReceiveData:` 45 | - `connectionDidFinishLoading:` 46 | - `connection:didFailWithError:` 47 | - `connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:` 48 | - `connection:willCacheResponse:` 49 | - `connectionShouldUseCredentialStorage:` 50 | - `connection:needNewBodyStream:` 51 | - `connection:willSendRequestForAuthenticationChallenge:` 52 | 53 | If any of these methods are overridden in a subclass, they _must_ call the `super` implementation first. 54 | 55 | ## Callbacks and Completion Blocks 56 | 57 | The built-in `completionBlock` provided by `NSOperation` allows for custom behavior to be executed after the request finishes. It is a common pattern for class constructors in subclasses to take callback block parameters, and execute them conditionally in the body of its `completionBlock`. Make sure to handle cancelled operations appropriately when setting a `completionBlock` (i.e. returning early before parsing response data). See the implementation of any of the `AFHTTPRequestOperation` subclasses for an example of this. 58 | 59 | Subclasses are strongly discouraged from overriding `setCompletionBlock:`, as `AFURLConnectionOperation`'s implementation includes a workaround to mitigate retain cycles, and what Apple rather ominously refers to as ["The Deallocation Problem"](http://developer.apple.com/library/ios/#technotes/tn2109/). 60 | 61 | ## SSL Pinning 62 | 63 | Relying on the CA trust model to validate SSL certificates exposes your app to security vulnerabilities, such as man-in-the-middle attacks. For applications that connect to known servers, SSL certificate pinning provides an increased level of security, by checking server certificate validity against those specified in the app bundle. 64 | 65 | SSL with certificate pinning is strongly recommended for any application that transmits sensitive information to an external webservice. 66 | 67 | Connections will be validated on all matching certificates with a `.cer` extension in the bundle root. 68 | 69 | ## App Extensions 70 | 71 | When using AFNetworking in an App Extension, `#define AF_APP_EXTENSIONS` to avoid using unavailable APIs. 72 | 73 | ## NSCoding & NSCopying Conformance 74 | 75 | `AFURLConnectionOperation` conforms to the `NSCoding` and `NSCopying` protocols, allowing operations to be archived to disk, and copied in memory, respectively. However, because of the intrinsic limitations of capturing the exact state of an operation at a particular moment, there are some important caveats to keep in mind: 76 | 77 | ### NSCoding Caveats 78 | 79 | - Encoded operations do not include any block or stream properties. Be sure to set `completionBlock`, `outputStream`, and any callback blocks as necessary when using `-initWithCoder:` or `NSKeyedUnarchiver`. 80 | - Operations are paused on `encodeWithCoder:`. If the operation was encoded while paused or still executing, its archived state will return `YES` for `isReady`. Otherwise, the state of an operation when encoding will remain unchanged. 81 | 82 | ### NSCopying Caveats 83 | 84 | - `-copy` and `-copyWithZone:` return a new operation with the `NSURLRequest` of the original. So rather than an exact copy of the operation at that particular instant, the copying mechanism returns a completely new instance, which can be useful for retrying operations. 85 | - A copy of an operation will not include the `outputStream` of the original. 86 | - Operation copies do not include `completionBlock`, as it often strongly captures a reference to `self`, which would otherwise have the unintuitive side-effect of pointing to the _original_ operation when copied. 87 | */ 88 | 89 | @interface AFURLConnectionOperation : NSOperation 90 | 91 | ///------------------------------- 92 | /// @name Accessing Run Loop Modes 93 | ///------------------------------- 94 | 95 | /** 96 | The run loop modes in which the operation will run on the network thread. By default, this is a single-member set containing `NSRunLoopCommonModes`. 97 | */ 98 | @property (nonatomic, strong) NSSet *runLoopModes; 99 | 100 | ///----------------------------------------- 101 | /// @name Getting URL Connection Information 102 | ///----------------------------------------- 103 | 104 | /** 105 | The request used by the operation's connection. 106 | */ 107 | @property (readonly, nonatomic, strong) NSURLRequest *request; 108 | 109 | /** 110 | The last response received by the operation's connection. 111 | */ 112 | @property (readonly, nonatomic, strong) NSURLResponse *response; 113 | 114 | /** 115 | The error, if any, that occurred in the lifecycle of the request. 116 | */ 117 | @property (readonly, nonatomic, strong) NSError *error; 118 | 119 | ///---------------------------- 120 | /// @name Getting Response Data 121 | ///---------------------------- 122 | 123 | /** 124 | The data received during the request. 125 | */ 126 | @property (readonly, nonatomic, strong) NSData *responseData; 127 | 128 | /** 129 | The string representation of the response data. 130 | */ 131 | @property (readonly, nonatomic, copy) NSString *responseString; 132 | 133 | /** 134 | The string encoding of the response. 135 | 136 | If the response does not specify a valid string encoding, `responseStringEncoding` will return `NSUTF8StringEncoding`. 137 | */ 138 | @property (readonly, nonatomic, assign) NSStringEncoding responseStringEncoding; 139 | 140 | ///------------------------------- 141 | /// @name Managing URL Credentials 142 | ///------------------------------- 143 | 144 | /** 145 | Whether the URL connection should consult the credential storage for authenticating the connection. `YES` by default. 146 | 147 | This is the value that is returned in the `NSURLConnectionDelegate` method `-connectionShouldUseCredentialStorage:`. 148 | */ 149 | @property (nonatomic, assign) BOOL shouldUseCredentialStorage; 150 | 151 | /** 152 | The credential used for authentication challenges in `-connection:didReceiveAuthenticationChallenge:`. 153 | 154 | This will be overridden by any shared credentials that exist for the username or password of the request URL, if present. 155 | */ 156 | @property (nonatomic, strong) NSURLCredential *credential; 157 | 158 | ///------------------------------- 159 | /// @name Managing Security Policy 160 | ///------------------------------- 161 | 162 | /** 163 | The security policy used to evaluate server trust for secure connections. 164 | */ 165 | @property (nonatomic, strong) AFSecurityPolicy *securityPolicy; 166 | 167 | ///------------------------ 168 | /// @name Accessing Streams 169 | ///------------------------ 170 | 171 | /** 172 | The input stream used to read data to be sent during the request. 173 | 174 | This property acts as a proxy to the `HTTPBodyStream` property of `request`. 175 | */ 176 | @property (nonatomic, strong) NSInputStream *inputStream; 177 | 178 | /** 179 | The output stream that is used to write data received until the request is finished. 180 | 181 | By default, data is accumulated into a buffer that is stored into `responseData` upon completion of the request, with the intermediary `outputStream` property set to `nil`. When `outputStream` is set, the data will not be accumulated into an internal buffer, and as a result, the `responseData` property of the completed request will be `nil`. The output stream will be scheduled in the network thread runloop upon being set. 182 | */ 183 | @property (nonatomic, strong) NSOutputStream *outputStream; 184 | 185 | ///--------------------------------- 186 | /// @name Managing Callback Queues 187 | ///--------------------------------- 188 | 189 | /** 190 | The dispatch queue for `completionBlock`. If `NULL` (default), the main queue is used. 191 | */ 192 | @property (nonatomic, strong) dispatch_queue_t completionQueue; 193 | 194 | /** 195 | The dispatch group for `completionBlock`. If `NULL` (default), a private dispatch group is used. 196 | */ 197 | @property (nonatomic, strong) dispatch_group_t completionGroup; 198 | 199 | ///--------------------------------------------- 200 | /// @name Managing Request Operation Information 201 | ///--------------------------------------------- 202 | 203 | /** 204 | The user info dictionary for the receiver. 205 | */ 206 | @property (nonatomic, strong) NSDictionary *userInfo; 207 | 208 | ///------------------------------------------------------ 209 | /// @name Initializing an AFURLConnectionOperation Object 210 | ///------------------------------------------------------ 211 | 212 | /** 213 | Initializes and returns a newly allocated operation object with a url connection configured with the specified url request. 214 | 215 | This is the designated initializer. 216 | 217 | @param urlRequest The request object to be used by the operation connection. 218 | */ 219 | - (instancetype)initWithRequest:(NSURLRequest *)urlRequest NS_DESIGNATED_INITIALIZER; 220 | 221 | ///---------------------------------- 222 | /// @name Pausing / Resuming Requests 223 | ///---------------------------------- 224 | 225 | /** 226 | Pauses the execution of the request operation. 227 | 228 | A paused operation returns `NO` for `-isReady`, `-isExecuting`, and `-isFinished`. As such, it will remain in an `NSOperationQueue` until it is either cancelled or resumed. Pausing a finished, cancelled, or paused operation has no effect. 229 | */ 230 | - (void)pause; 231 | 232 | /** 233 | Whether the request operation is currently paused. 234 | 235 | @return `YES` if the operation is currently paused, otherwise `NO`. 236 | */ 237 | - (BOOL)isPaused; 238 | 239 | /** 240 | Resumes the execution of the paused request operation. 241 | 242 | Pause/Resume behavior varies depending on the underlying implementation for the operation class. In its base implementation, resuming a paused requests restarts the original request. However, since HTTP defines a specification for how to request a specific content range, `AFHTTPRequestOperation` will resume downloading the request from where it left off, instead of restarting the original request. 243 | */ 244 | - (void)resume; 245 | 246 | ///---------------------------------------------- 247 | /// @name Configuring Backgrounding Task Behavior 248 | ///---------------------------------------------- 249 | 250 | /** 251 | Specifies that the operation should continue execution after the app has entered the background, and the expiration handler for that background task. 252 | 253 | @param handler A handler to be called shortly before the application’s remaining background time reaches 0. The handler is wrapped in a block that cancels the operation, and cleans up and marks the end of execution, unlike the `handler` parameter in `UIApplication -beginBackgroundTaskWithExpirationHandler:`, which expects this to be done in the handler itself. The handler is called synchronously on the main thread, thus blocking the application’s suspension momentarily while the application is notified. 254 | */ 255 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && !defined(AF_APP_EXTENSIONS) 256 | - (void)setShouldExecuteAsBackgroundTaskWithExpirationHandler:(void (^)(void))handler; 257 | #endif 258 | 259 | ///--------------------------------- 260 | /// @name Setting Progress Callbacks 261 | ///--------------------------------- 262 | 263 | /** 264 | Sets a callback to be called when an undetermined number of bytes have been uploaded to the server. 265 | 266 | @param block A block object to be called when an undetermined number of bytes have been uploaded to the server. This block has no return value and takes three arguments: the number of bytes written since the last time the upload progress block was called, the total bytes written, and the total bytes expected to be written during the request, as initially determined by the length of the HTTP body. This block may be called multiple times, and will execute on the main thread. 267 | */ 268 | - (void)setUploadProgressBlock:(void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))block; 269 | 270 | /** 271 | Sets a callback to be called when an undetermined number of bytes have been downloaded from the server. 272 | 273 | @param block A block object to be called when an undetermined number of bytes have been downloaded from the server. This block has no return value and takes three arguments: the number of bytes read since the last time the download progress block was called, the total bytes read, and the total bytes expected to be read during the request, as initially determined by the expected content size of the `NSHTTPURLResponse` object. This block may be called multiple times, and will execute on the main thread. 274 | */ 275 | - (void)setDownloadProgressBlock:(void (^)(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead))block; 276 | 277 | ///------------------------------------------------- 278 | /// @name Setting NSURLConnection Delegate Callbacks 279 | ///------------------------------------------------- 280 | 281 | /** 282 | Sets a block to be executed when the connection will authenticate a challenge in order to download its request, as handled by the `NSURLConnectionDelegate` method `connection:willSendRequestForAuthenticationChallenge:`. 283 | 284 | @param block A block object to be executed when the connection will authenticate a challenge in order to download its request. The block has no return type and takes two arguments: the URL connection object, and the challenge that must be authenticated. This block must invoke one of the challenge-responder methods (NSURLAuthenticationChallengeSender protocol). 285 | 286 | If `allowsInvalidSSLCertificate` is set to YES, `connection:willSendRequestForAuthenticationChallenge:` will attempt to have the challenge sender use credentials with invalid SSL certificates. 287 | */ 288 | - (void)setWillSendRequestForAuthenticationChallengeBlock:(void (^)(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge))block; 289 | 290 | /** 291 | Sets a block to be executed when the server redirects the request from one URL to another URL, or when the request URL changed by the `NSURLProtocol` subclass handling the request in order to standardize its format, as handled by the `NSURLConnectionDataDelegate` method `connection:willSendRequest:redirectResponse:`. 292 | 293 | @param block A block object to be executed when the request URL was changed. The block returns an `NSURLRequest` object, the URL request to redirect, and takes three arguments: the URL connection object, the the proposed redirected request, and the URL response that caused the redirect. 294 | */ 295 | - (void)setRedirectResponseBlock:(NSURLRequest * (^)(NSURLConnection *connection, NSURLRequest *request, NSURLResponse *redirectResponse))block; 296 | 297 | 298 | /** 299 | Sets a block to be executed to modify the response a connection will cache, if any, as handled by the `NSURLConnectionDelegate` method `connection:willCacheResponse:`. 300 | 301 | @param block A block object to be executed to determine what response a connection will cache, if any. The block returns an `NSCachedURLResponse` object, the cached response to store in memory or `nil` to prevent the response from being cached, and takes two arguments: the URL connection object, and the cached response provided for the request. 302 | */ 303 | - (void)setCacheResponseBlock:(NSCachedURLResponse * (^)(NSURLConnection *connection, NSCachedURLResponse *cachedResponse))block; 304 | 305 | /// 306 | 307 | /** 308 | 309 | */ 310 | + (NSArray *)batchOfRequestOperations:(NSArray *)operations 311 | progressBlock:(void (^)(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations))progressBlock 312 | completionBlock:(void (^)(NSArray *operations))completionBlock; 313 | 314 | @end 315 | 316 | ///-------------------- 317 | /// @name Notifications 318 | ///-------------------- 319 | 320 | /** 321 | Posted when an operation begins executing. 322 | */ 323 | extern NSString * const AFNetworkingOperationDidStartNotification; 324 | 325 | /** 326 | Posted when an operation finishes. 327 | */ 328 | extern NSString * const AFNetworkingOperationDidFinishNotification; 329 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/AFNetworking/AFURLRequestSerialization.h: -------------------------------------------------------------------------------- 1 | // AFURLRequestSerialization.h 2 | // 3 | // Copyright (c) 2013-2015 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 25 | #import 26 | #endif 27 | 28 | /** 29 | The `AFURLRequestSerialization` protocol is adopted by an object that encodes parameters for a specified HTTP requests. Request serializers may encode parameters as query strings, HTTP bodies, setting the appropriate HTTP header fields as necessary. 30 | 31 | For example, a JSON request serializer may set the HTTP body of the request to a JSON representation, and set the `Content-Type` HTTP header field value to `application/json`. 32 | */ 33 | @protocol AFURLRequestSerialization 34 | 35 | /** 36 | Returns a request with the specified parameters encoded into a copy of the original request. 37 | 38 | @param request The original request. 39 | @param parameters The parameters to be encoded. 40 | @param error The error that occurred while attempting to encode the request parameters. 41 | 42 | @return A serialized request. 43 | */ 44 | - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request 45 | withParameters:(id)parameters 46 | error:(NSError * __autoreleasing *)error; 47 | 48 | @end 49 | 50 | #pragma mark - 51 | 52 | /** 53 | 54 | */ 55 | typedef NS_ENUM(NSUInteger, AFHTTPRequestQueryStringSerializationStyle) { 56 | AFHTTPRequestQueryStringDefaultStyle = 0, 57 | }; 58 | 59 | @protocol AFMultipartFormData; 60 | 61 | /** 62 | `AFHTTPRequestSerializer` conforms to the `AFURLRequestSerialization` & `AFURLResponseSerialization` protocols, offering a concrete base implementation of query string / URL form-encoded parameter serialization and default request headers, as well as response status code and content type validation. 63 | 64 | Any request or response serializer dealing with HTTP is encouraged to subclass `AFHTTPRequestSerializer` in order to ensure consistent default behavior. 65 | */ 66 | @interface AFHTTPRequestSerializer : NSObject 67 | 68 | /** 69 | The string encoding used to serialize parameters. `NSUTF8StringEncoding` by default. 70 | */ 71 | @property (nonatomic, assign) NSStringEncoding stringEncoding; 72 | 73 | /** 74 | Whether created requests can use the device’s cellular radio (if present). `YES` by default. 75 | 76 | @see NSMutableURLRequest -setAllowsCellularAccess: 77 | */ 78 | @property (nonatomic, assign) BOOL allowsCellularAccess; 79 | 80 | /** 81 | The cache policy of created requests. `NSURLRequestUseProtocolCachePolicy` by default. 82 | 83 | @see NSMutableURLRequest -setCachePolicy: 84 | */ 85 | @property (nonatomic, assign) NSURLRequestCachePolicy cachePolicy; 86 | 87 | /** 88 | Whether created requests should use the default cookie handling. `YES` by default. 89 | 90 | @see NSMutableURLRequest -setHTTPShouldHandleCookies: 91 | */ 92 | @property (nonatomic, assign) BOOL HTTPShouldHandleCookies; 93 | 94 | /** 95 | Whether created requests can continue transmitting data before receiving a response from an earlier transmission. `NO` by default 96 | 97 | @see NSMutableURLRequest -setHTTPShouldUsePipelining: 98 | */ 99 | @property (nonatomic, assign) BOOL HTTPShouldUsePipelining; 100 | 101 | /** 102 | The network service type for created requests. `NSURLNetworkServiceTypeDefault` by default. 103 | 104 | @see NSMutableURLRequest -setNetworkServiceType: 105 | */ 106 | @property (nonatomic, assign) NSURLRequestNetworkServiceType networkServiceType; 107 | 108 | /** 109 | The timeout interval, in seconds, for created requests. The default timeout interval is 60 seconds. 110 | 111 | @see NSMutableURLRequest -setTimeoutInterval: 112 | */ 113 | @property (nonatomic, assign) NSTimeInterval timeoutInterval; 114 | 115 | ///--------------------------------------- 116 | /// @name Configuring HTTP Request Headers 117 | ///--------------------------------------- 118 | 119 | /** 120 | Default HTTP header field values to be applied to serialized requests. By default, these include the following: 121 | 122 | - `Accept-Language` with the contents of `NSLocale +preferredLanguages` 123 | - `User-Agent` with the contents of various bundle identifiers and OS designations 124 | 125 | @discussion To add or remove default request headers, use `setValue:forHTTPHeaderField:`. 126 | */ 127 | @property (readonly, nonatomic, strong) NSDictionary *HTTPRequestHeaders; 128 | 129 | /** 130 | Creates and returns a serializer with default configuration. 131 | */ 132 | + (instancetype)serializer; 133 | 134 | /** 135 | Sets the value for the HTTP headers set in request objects made by the HTTP client. If `nil`, removes the existing value for that header. 136 | 137 | @param field The HTTP header to set a default value for 138 | @param value The value set as default for the specified header, or `nil` 139 | */ 140 | - (void)setValue:(NSString *)value 141 | forHTTPHeaderField:(NSString *)field; 142 | 143 | /** 144 | Returns the value for the HTTP headers set in the request serializer. 145 | 146 | @param field The HTTP header to retrieve the default value for 147 | 148 | @return The value set as default for the specified header, or `nil` 149 | */ 150 | - (NSString *)valueForHTTPHeaderField:(NSString *)field; 151 | 152 | /** 153 | Sets the "Authorization" HTTP header set in request objects made by the HTTP client to a basic authentication value with Base64-encoded username and password. This overwrites any existing value for this header. 154 | 155 | @param username The HTTP basic auth username 156 | @param password The HTTP basic auth password 157 | */ 158 | - (void)setAuthorizationHeaderFieldWithUsername:(NSString *)username 159 | password:(NSString *)password; 160 | 161 | /** 162 | @deprecated This method has been deprecated. Use -setValue:forHTTPHeaderField: instead. 163 | */ 164 | - (void)setAuthorizationHeaderFieldWithToken:(NSString *)token DEPRECATED_ATTRIBUTE; 165 | 166 | 167 | /** 168 | Clears any existing value for the "Authorization" HTTP header. 169 | */ 170 | - (void)clearAuthorizationHeader; 171 | 172 | ///------------------------------------------------------- 173 | /// @name Configuring Query String Parameter Serialization 174 | ///------------------------------------------------------- 175 | 176 | /** 177 | HTTP methods for which serialized requests will encode parameters as a query string. `GET`, `HEAD`, and `DELETE` by default. 178 | */ 179 | @property (nonatomic, strong) NSSet *HTTPMethodsEncodingParametersInURI; 180 | 181 | /** 182 | Set the method of query string serialization according to one of the pre-defined styles. 183 | 184 | @param style The serialization style. 185 | 186 | @see AFHTTPRequestQueryStringSerializationStyle 187 | */ 188 | - (void)setQueryStringSerializationWithStyle:(AFHTTPRequestQueryStringSerializationStyle)style; 189 | 190 | /** 191 | Set the a custom method of query string serialization according to the specified block. 192 | 193 | @param block A block that defines a process of encoding parameters into a query string. This block returns the query string and takes three arguments: the request, the parameters to encode, and the error that occurred when attempting to encode parameters for the given request. 194 | */ 195 | - (void)setQueryStringSerializationWithBlock:(NSString * (^)(NSURLRequest *request, id parameters, NSError * __autoreleasing *error))block; 196 | 197 | ///------------------------------- 198 | /// @name Creating Request Objects 199 | ///------------------------------- 200 | 201 | /** 202 | @deprecated This method has been deprecated. Use -requestWithMethod:URLString:parameters:error: instead. 203 | */ 204 | - (NSMutableURLRequest *)requestWithMethod:(NSString *)method 205 | URLString:(NSString *)URLString 206 | parameters:(id)parameters DEPRECATED_ATTRIBUTE; 207 | 208 | /** 209 | Creates an `NSMutableURLRequest` object with the specified HTTP method and URL string. 210 | 211 | If the HTTP method is `GET`, `HEAD`, or `DELETE`, the parameters will be used to construct a url-encoded query string that is appended to the request's URL. Otherwise, the parameters will be encoded according to the value of the `parameterEncoding` property, and set as the request body. 212 | 213 | @param method The HTTP method for the request, such as `GET`, `POST`, `PUT`, or `DELETE`. This parameter must not be `nil`. 214 | @param URLString The URL string used to create the request URL. 215 | @param parameters The parameters to be either set as a query string for `GET` requests, or the request HTTP body. 216 | @param error The error that occured while constructing the request. 217 | 218 | @return An `NSMutableURLRequest` object. 219 | */ 220 | - (NSMutableURLRequest *)requestWithMethod:(NSString *)method 221 | URLString:(NSString *)URLString 222 | parameters:(id)parameters 223 | error:(NSError * __autoreleasing *)error; 224 | 225 | /** 226 | @deprecated This method has been deprecated. Use -multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:error: instead. 227 | */ 228 | - (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method 229 | URLString:(NSString *)URLString 230 | parameters:(NSDictionary *)parameters 231 | constructingBodyWithBlock:(void (^)(id formData))block DEPRECATED_ATTRIBUTE; 232 | 233 | /** 234 | Creates an `NSMutableURLRequest` object with the specified HTTP method and URLString, and constructs a `multipart/form-data` HTTP body, using the specified parameters and multipart form data block. See http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.2 235 | 236 | Multipart form requests are automatically streamed, reading files directly from disk along with in-memory data in a single HTTP body. The resulting `NSMutableURLRequest` object has an `HTTPBodyStream` property, so refrain from setting `HTTPBodyStream` or `HTTPBody` on this request object, as it will clear out the multipart form body stream. 237 | 238 | @param method The HTTP method for the request. This parameter must not be `GET` or `HEAD`, or `nil`. 239 | @param URLString The URL string used to create the request URL. 240 | @param parameters The parameters to be encoded and set in the request HTTP body. 241 | @param block A block that takes a single argument and appends data to the HTTP body. The block argument is an object adopting the `AFMultipartFormData` protocol. 242 | @param error The error that occured while constructing the request. 243 | 244 | @return An `NSMutableURLRequest` object 245 | */ 246 | - (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method 247 | URLString:(NSString *)URLString 248 | parameters:(NSDictionary *)parameters 249 | constructingBodyWithBlock:(void (^)(id formData))block 250 | error:(NSError * __autoreleasing *)error; 251 | 252 | /** 253 | Creates an `NSMutableURLRequest` by removing the `HTTPBodyStream` from a request, and asynchronously writing its contents into the specified file, invoking the completion handler when finished. 254 | 255 | @param request The multipart form request. The `HTTPBodyStream` property of `request` must not be `nil`. 256 | @param fileURL The file URL to write multipart form contents to. 257 | @param handler A handler block to execute. 258 | 259 | @discussion There is a bug in `NSURLSessionTask` that causes requests to not send a `Content-Length` header when streaming contents from an HTTP body, which is notably problematic when interacting with the Amazon S3 webservice. As a workaround, this method takes a request constructed with `multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:error:`, or any other request with an `HTTPBodyStream`, writes the contents to the specified file and returns a copy of the original request with the `HTTPBodyStream` property set to `nil`. From here, the file can either be passed to `AFURLSessionManager -uploadTaskWithRequest:fromFile:progress:completionHandler:`, or have its contents read into an `NSData` that's assigned to the `HTTPBody` property of the request. 260 | 261 | @see https://github.com/AFNetworking/AFNetworking/issues/1398 262 | */ 263 | - (NSMutableURLRequest *)requestWithMultipartFormRequest:(NSURLRequest *)request 264 | writingStreamContentsToFile:(NSURL *)fileURL 265 | completionHandler:(void (^)(NSError *error))handler; 266 | 267 | @end 268 | 269 | #pragma mark - 270 | 271 | /** 272 | The `AFMultipartFormData` protocol defines the methods supported by the parameter in the block argument of `AFHTTPRequestSerializer -multipartFormRequestWithMethod:URLString:parameters:constructingBodyWithBlock:`. 273 | */ 274 | @protocol AFMultipartFormData 275 | 276 | /** 277 | Appends the HTTP header `Content-Disposition: file; filename=#{generated filename}; name=#{name}"` and `Content-Type: #{generated mimeType}`, followed by the encoded file data and the multipart form boundary. 278 | 279 | The filename and MIME type for this data in the form will be automatically generated, using the last path component of the `fileURL` and system associated MIME type for the `fileURL` extension, respectively. 280 | 281 | @param fileURL The URL corresponding to the file whose content will be appended to the form. This parameter must not be `nil`. 282 | @param name The name to be associated with the specified data. This parameter must not be `nil`. 283 | @param error If an error occurs, upon return contains an `NSError` object that describes the problem. 284 | 285 | @return `YES` if the file data was successfully appended, otherwise `NO`. 286 | */ 287 | - (BOOL)appendPartWithFileURL:(NSURL *)fileURL 288 | name:(NSString *)name 289 | error:(NSError * __autoreleasing *)error; 290 | 291 | /** 292 | Appends the HTTP header `Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`, followed by the encoded file data and the multipart form boundary. 293 | 294 | @param fileURL The URL corresponding to the file whose content will be appended to the form. This parameter must not be `nil`. 295 | @param name The name to be associated with the specified data. This parameter must not be `nil`. 296 | @param fileName The file name to be used in the `Content-Disposition` header. This parameter must not be `nil`. 297 | @param mimeType The declared MIME type of the file data. This parameter must not be `nil`. 298 | @param error If an error occurs, upon return contains an `NSError` object that describes the problem. 299 | 300 | @return `YES` if the file data was successfully appended otherwise `NO`. 301 | */ 302 | - (BOOL)appendPartWithFileURL:(NSURL *)fileURL 303 | name:(NSString *)name 304 | fileName:(NSString *)fileName 305 | mimeType:(NSString *)mimeType 306 | error:(NSError * __autoreleasing *)error; 307 | 308 | /** 309 | Appends the HTTP header `Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`, followed by the data from the input stream and the multipart form boundary. 310 | 311 | @param inputStream The input stream to be appended to the form data 312 | @param name The name to be associated with the specified input stream. This parameter must not be `nil`. 313 | @param fileName The filename to be associated with the specified input stream. This parameter must not be `nil`. 314 | @param length The length of the specified input stream in bytes. 315 | @param mimeType The MIME type of the specified data. (For example, the MIME type for a JPEG image is image/jpeg.) For a list of valid MIME types, see http://www.iana.org/assignments/media-types/. This parameter must not be `nil`. 316 | */ 317 | - (void)appendPartWithInputStream:(NSInputStream *)inputStream 318 | name:(NSString *)name 319 | fileName:(NSString *)fileName 320 | length:(int64_t)length 321 | mimeType:(NSString *)mimeType; 322 | 323 | /** 324 | Appends the HTTP header `Content-Disposition: file; filename=#{filename}; name=#{name}"` and `Content-Type: #{mimeType}`, followed by the encoded file data and the multipart form boundary. 325 | 326 | @param data The data to be encoded and appended to the form data. 327 | @param name The name to be associated with the specified data. This parameter must not be `nil`. 328 | @param fileName The filename to be associated with the specified data. This parameter must not be `nil`. 329 | @param mimeType The MIME type of the specified data. (For example, the MIME type for a JPEG image is image/jpeg.) For a list of valid MIME types, see http://www.iana.org/assignments/media-types/. This parameter must not be `nil`. 330 | */ 331 | - (void)appendPartWithFileData:(NSData *)data 332 | name:(NSString *)name 333 | fileName:(NSString *)fileName 334 | mimeType:(NSString *)mimeType; 335 | 336 | /** 337 | Appends the HTTP headers `Content-Disposition: form-data; name=#{name}"`, followed by the encoded data and the multipart form boundary. 338 | 339 | @param data The data to be encoded and appended to the form data. 340 | @param name The name to be associated with the specified data. This parameter must not be `nil`. 341 | */ 342 | 343 | - (void)appendPartWithFormData:(NSData *)data 344 | name:(NSString *)name; 345 | 346 | 347 | /** 348 | Appends HTTP headers, followed by the encoded data and the multipart form boundary. 349 | 350 | @param headers The HTTP headers to be appended to the form data. 351 | @param body The data to be encoded and appended to the form data. This parameter must not be `nil`. 352 | */ 353 | - (void)appendPartWithHeaders:(NSDictionary *)headers 354 | body:(NSData *)body; 355 | 356 | /** 357 | Throttles request bandwidth by limiting the packet size and adding a delay for each chunk read from the upload stream. 358 | 359 | When uploading over a 3G or EDGE connection, requests may fail with "request body stream exhausted". Setting a maximum packet size and delay according to the recommended values (`kAFUploadStream3GSuggestedPacketSize` and `kAFUploadStream3GSuggestedDelay`) lowers the risk of the input stream exceeding its allocated bandwidth. Unfortunately, there is no definite way to distinguish between a 3G, EDGE, or LTE connection over `NSURLConnection`. As such, it is not recommended that you throttle bandwidth based solely on network reachability. Instead, you should consider checking for the "request body stream exhausted" in a failure block, and then retrying the request with throttled bandwidth. 360 | 361 | @param numberOfBytes Maximum packet size, in number of bytes. The default packet size for an input stream is 16kb. 362 | @param delay Duration of delay each time a packet is read. By default, no delay is set. 363 | */ 364 | - (void)throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes 365 | delay:(NSTimeInterval)delay; 366 | 367 | @end 368 | 369 | #pragma mark - 370 | 371 | /** 372 | `AFJSONRequestSerializer` is a subclass of `AFHTTPRequestSerializer` that encodes parameters as JSON using `NSJSONSerialization`, setting the `Content-Type` of the encoded request to `application/json`. 373 | */ 374 | @interface AFJSONRequestSerializer : AFHTTPRequestSerializer 375 | 376 | /** 377 | Options for writing the request JSON data from Foundation objects. For possible values, see the `NSJSONSerialization` documentation section "NSJSONWritingOptions". `0` by default. 378 | */ 379 | @property (nonatomic, assign) NSJSONWritingOptions writingOptions; 380 | 381 | /** 382 | Creates and returns a JSON serializer with specified reading and writing options. 383 | 384 | @param writingOptions The specified JSON writing options. 385 | */ 386 | + (instancetype)serializerWithWritingOptions:(NSJSONWritingOptions)writingOptions; 387 | 388 | @end 389 | 390 | #pragma mark - 391 | 392 | /** 393 | `AFPropertyListRequestSerializer` is a subclass of `AFHTTPRequestSerializer` that encodes parameters as JSON using `NSPropertyListSerializer`, setting the `Content-Type` of the encoded request to `application/x-plist`. 394 | */ 395 | @interface AFPropertyListRequestSerializer : AFHTTPRequestSerializer 396 | 397 | /** 398 | The property list format. Possible values are described in "NSPropertyListFormat". 399 | */ 400 | @property (nonatomic, assign) NSPropertyListFormat format; 401 | 402 | /** 403 | @warning The `writeOptions` property is currently unused. 404 | */ 405 | @property (nonatomic, assign) NSPropertyListWriteOptions writeOptions; 406 | 407 | /** 408 | Creates and returns a property list serializer with a specified format, read options, and write options. 409 | 410 | @param format The property list format. 411 | @param writeOptions The property list write options. 412 | 413 | @warning The `writeOptions` property is currently unused. 414 | */ 415 | + (instancetype)serializerWithFormat:(NSPropertyListFormat)format 416 | writeOptions:(NSPropertyListWriteOptions)writeOptions; 417 | 418 | @end 419 | 420 | #pragma mark - 421 | 422 | ///---------------- 423 | /// @name Constants 424 | ///---------------- 425 | 426 | /** 427 | ## Error Domains 428 | 429 | The following error domain is predefined. 430 | 431 | - `NSString * const AFURLRequestSerializationErrorDomain` 432 | 433 | ### Constants 434 | 435 | `AFURLRequestSerializationErrorDomain` 436 | AFURLRequestSerializer errors. Error codes for `AFURLRequestSerializationErrorDomain` correspond to codes in `NSURLErrorDomain`. 437 | */ 438 | extern NSString * const AFURLRequestSerializationErrorDomain; 439 | 440 | /** 441 | ## User info dictionary keys 442 | 443 | These keys may exist in the user info dictionary, in addition to those defined for NSError. 444 | 445 | - `NSString * const AFNetworkingOperationFailingURLRequestErrorKey` 446 | 447 | ### Constants 448 | 449 | `AFNetworkingOperationFailingURLRequestErrorKey` 450 | The corresponding value is an `NSURLRequest` containing the request of the operation associated with an error. This key is only present in the `AFURLRequestSerializationErrorDomain`. 451 | */ 452 | extern NSString * const AFNetworkingOperationFailingURLRequestErrorKey; 453 | 454 | /** 455 | ## Throttling Bandwidth for HTTP Request Input Streams 456 | 457 | @see -throttleBandwidthWithPacketSize:delay: 458 | 459 | ### Constants 460 | 461 | `kAFUploadStream3GSuggestedPacketSize` 462 | Maximum packet size, in number of bytes. Equal to 16kb. 463 | 464 | `kAFUploadStream3GSuggestedDelay` 465 | Duration of delay each time a packet is read. Equal to 0.2 seconds. 466 | */ 467 | extern NSUInteger const kAFUploadStream3GSuggestedPacketSize; 468 | extern NSTimeInterval const kAFUploadStream3GSuggestedDelay; 469 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/AFNetworking/AFURLResponseSerialization.h: -------------------------------------------------------------------------------- 1 | // AFURLResponseSerialization.h 2 | // 3 | // Copyright (c) 2013-2015 AFNetworking (http://afnetworking.com) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | #import 25 | 26 | /** 27 | The `AFURLResponseSerialization` protocol is adopted by an object that decodes data into a more useful object representation, according to details in the server response. Response serializers may additionally perform validation on the incoming response and data. 28 | 29 | For example, a JSON response serializer may check for an acceptable status code (`2XX` range) and content type (`application/json`), decoding a valid JSON response into an object. 30 | */ 31 | @protocol AFURLResponseSerialization 32 | 33 | /** 34 | The response object decoded from the data associated with a specified response. 35 | 36 | @param response The response to be processed. 37 | @param data The response data to be decoded. 38 | @param error The error that occurred while attempting to decode the response data. 39 | 40 | @return The object decoded from the specified response data. 41 | */ 42 | - (id)responseObjectForResponse:(NSURLResponse *)response 43 | data:(NSData *)data 44 | error:(NSError *__autoreleasing *)error; 45 | 46 | @end 47 | 48 | #pragma mark - 49 | 50 | /** 51 | `AFHTTPResponseSerializer` conforms to the `AFURLRequestSerialization` & `AFURLResponseSerialization` protocols, offering a concrete base implementation of query string / URL form-encoded parameter serialization and default request headers, as well as response status code and content type validation. 52 | 53 | Any request or response serializer dealing with HTTP is encouraged to subclass `AFHTTPResponseSerializer` in order to ensure consistent default behavior. 54 | */ 55 | @interface AFHTTPResponseSerializer : NSObject 56 | 57 | - (instancetype) init; 58 | 59 | /** 60 | The string encoding used to serialize data received from the server, when no string encoding is specified by the response. `NSUTF8StringEncoding` by default. 61 | */ 62 | @property (nonatomic, assign) NSStringEncoding stringEncoding; 63 | 64 | /** 65 | Creates and returns a serializer with default configuration. 66 | */ 67 | + (instancetype)serializer; 68 | 69 | ///----------------------------------------- 70 | /// @name Configuring Response Serialization 71 | ///----------------------------------------- 72 | 73 | /** 74 | The acceptable HTTP status codes for responses. When non-`nil`, responses with status codes not contained by the set will result in an error during validation. 75 | 76 | See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html 77 | */ 78 | @property (nonatomic, copy) NSIndexSet *acceptableStatusCodes; 79 | 80 | /** 81 | The acceptable MIME types for responses. When non-`nil`, responses with a `Content-Type` with MIME types that do not intersect with the set will result in an error during validation. 82 | */ 83 | @property (nonatomic, copy) NSSet *acceptableContentTypes; 84 | 85 | /** 86 | Validates the specified response and data. 87 | 88 | In its base implementation, this method checks for an acceptable status code and content type. Subclasses may wish to add other domain-specific checks. 89 | 90 | @param response The response to be validated. 91 | @param data The data associated with the response. 92 | @param error The error that occurred while attempting to validate the response. 93 | 94 | @return `YES` if the response is valid, otherwise `NO`. 95 | */ 96 | - (BOOL)validateResponse:(NSHTTPURLResponse *)response 97 | data:(NSData *)data 98 | error:(NSError *__autoreleasing *)error; 99 | 100 | @end 101 | 102 | #pragma mark - 103 | 104 | 105 | /** 106 | `AFJSONResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes JSON responses. 107 | 108 | By default, `AFJSONResponseSerializer` accepts the following MIME types, which includes the official standard, `application/json`, as well as other commonly-used types: 109 | 110 | - `application/json` 111 | - `text/json` 112 | - `text/javascript` 113 | */ 114 | @interface AFJSONResponseSerializer : AFHTTPResponseSerializer 115 | 116 | - (instancetype) init; 117 | 118 | /** 119 | Options for reading the response JSON data and creating the Foundation objects. For possible values, see the `NSJSONSerialization` documentation section "NSJSONReadingOptions". `0` by default. 120 | */ 121 | @property (nonatomic, assign) NSJSONReadingOptions readingOptions; 122 | 123 | /** 124 | Whether to remove keys with `NSNull` values from response JSON. Defaults to `NO`. 125 | */ 126 | @property (nonatomic, assign) BOOL removesKeysWithNullValues; 127 | 128 | /** 129 | Creates and returns a JSON serializer with specified reading and writing options. 130 | 131 | @param readingOptions The specified JSON reading options. 132 | */ 133 | + (instancetype)serializerWithReadingOptions:(NSJSONReadingOptions)readingOptions; 134 | 135 | @end 136 | 137 | #pragma mark - 138 | 139 | /** 140 | `AFXMLParserResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes XML responses as an `NSXMLParser` objects. 141 | 142 | By default, `AFXMLParserResponseSerializer` accepts the following MIME types, which includes the official standard, `application/xml`, as well as other commonly-used types: 143 | 144 | - `application/xml` 145 | - `text/xml` 146 | */ 147 | @interface AFXMLParserResponseSerializer : AFHTTPResponseSerializer 148 | 149 | @end 150 | 151 | #pragma mark - 152 | 153 | #ifdef __MAC_OS_X_VERSION_MIN_REQUIRED 154 | 155 | /** 156 | `AFXMLDocumentResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes XML responses as an `NSXMLDocument` objects. 157 | 158 | By default, `AFXMLDocumentResponseSerializer` accepts the following MIME types, which includes the official standard, `application/xml`, as well as other commonly-used types: 159 | 160 | - `application/xml` 161 | - `text/xml` 162 | */ 163 | @interface AFXMLDocumentResponseSerializer : AFHTTPResponseSerializer 164 | 165 | - (instancetype) init; 166 | 167 | /** 168 | Input and output options specifically intended for `NSXMLDocument` objects. For possible values, see the `NSJSONSerialization` documentation section "NSJSONReadingOptions". `0` by default. 169 | */ 170 | @property (nonatomic, assign) NSUInteger options; 171 | 172 | /** 173 | Creates and returns an XML document serializer with the specified options. 174 | 175 | @param mask The XML document options. 176 | */ 177 | + (instancetype)serializerWithXMLDocumentOptions:(NSUInteger)mask; 178 | 179 | @end 180 | 181 | #endif 182 | 183 | #pragma mark - 184 | 185 | /** 186 | `AFPropertyListResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes XML responses as an `NSXMLDocument` objects. 187 | 188 | By default, `AFPropertyListResponseSerializer` accepts the following MIME types: 189 | 190 | - `application/x-plist` 191 | */ 192 | @interface AFPropertyListResponseSerializer : AFHTTPResponseSerializer 193 | 194 | - (instancetype) init; 195 | 196 | /** 197 | The property list format. Possible values are described in "NSPropertyListFormat". 198 | */ 199 | @property (nonatomic, assign) NSPropertyListFormat format; 200 | 201 | /** 202 | The property list reading options. Possible values are described in "NSPropertyListMutabilityOptions." 203 | */ 204 | @property (nonatomic, assign) NSPropertyListReadOptions readOptions; 205 | 206 | /** 207 | Creates and returns a property list serializer with a specified format, read options, and write options. 208 | 209 | @param format The property list format. 210 | @param readOptions The property list reading options. 211 | */ 212 | + (instancetype)serializerWithFormat:(NSPropertyListFormat)format 213 | readOptions:(NSPropertyListReadOptions)readOptions; 214 | 215 | @end 216 | 217 | #pragma mark - 218 | 219 | /** 220 | `AFImageResponseSerializer` is a subclass of `AFHTTPResponseSerializer` that validates and decodes image responses. 221 | 222 | By default, `AFImageResponseSerializer` accepts the following MIME types, which correspond to the image formats supported by UIImage or NSImage: 223 | 224 | - `image/tiff` 225 | - `image/jpeg` 226 | - `image/gif` 227 | - `image/png` 228 | - `image/ico` 229 | - `image/x-icon` 230 | - `image/bmp` 231 | - `image/x-bmp` 232 | - `image/x-xbitmap` 233 | - `image/x-win-bitmap` 234 | */ 235 | @interface AFImageResponseSerializer : AFHTTPResponseSerializer 236 | 237 | #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 238 | /** 239 | The scale factor used when interpreting the image data to construct `responseImage`. Specifying a scale factor of 1.0 results in an image whose size matches the pixel-based dimensions of the image. Applying a different scale factor changes the size of the image as reported by the size property. This is set to the value of scale of the main screen by default, which automatically scales images for retina displays, for instance. 240 | */ 241 | @property (nonatomic, assign) CGFloat imageScale; 242 | 243 | /** 244 | Whether to automatically inflate response image data for compressed formats (such as PNG or JPEG). Enabling this can significantly improve drawing performance on iOS when used with `setCompletionBlockWithSuccess:failure:`, as it allows a bitmap representation to be constructed in the background rather than on the main thread. `YES` by default. 245 | */ 246 | @property (nonatomic, assign) BOOL automaticallyInflatesResponseImage; 247 | #endif 248 | 249 | @end 250 | 251 | #pragma mark - 252 | 253 | /** 254 | `AFCompoundSerializer` is a subclass of `AFHTTPResponseSerializer` that delegates the response serialization to the first `AFHTTPResponseSerializer` object that returns an object for `responseObjectForResponse:data:error:`, falling back on the default behavior of `AFHTTPResponseSerializer`. This is useful for supporting multiple potential types and structures of server responses with a single serializer. 255 | */ 256 | @interface AFCompoundResponseSerializer : AFHTTPResponseSerializer 257 | 258 | /** 259 | The component response serializers. 260 | */ 261 | @property (readonly, nonatomic, copy) NSArray *responseSerializers; 262 | 263 | /** 264 | Creates and returns a compound serializer comprised of the specified response serializers. 265 | 266 | @warning Each response serializer specified must be a subclass of `AFHTTPResponseSerializer`, and response to `-validateResponse:data:error:`. 267 | */ 268 | + (instancetype)compoundSerializerWithResponseSerializers:(NSArray *)responseSerializers; 269 | 270 | @end 271 | 272 | ///---------------- 273 | /// @name Constants 274 | ///---------------- 275 | 276 | /** 277 | ## Error Domains 278 | 279 | The following error domain is predefined. 280 | 281 | - `NSString * const AFURLResponseSerializationErrorDomain` 282 | 283 | ### Constants 284 | 285 | `AFURLResponseSerializationErrorDomain` 286 | AFURLResponseSerializer errors. Error codes for `AFURLResponseSerializationErrorDomain` correspond to codes in `NSURLErrorDomain`. 287 | */ 288 | extern NSString * const AFURLResponseSerializationErrorDomain; 289 | 290 | /** 291 | ## User info dictionary keys 292 | 293 | These keys may exist in the user info dictionary, in addition to those defined for NSError. 294 | 295 | - `NSString * const AFNetworkingOperationFailingURLResponseErrorKey` 296 | - `NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey` 297 | 298 | ### Constants 299 | 300 | `AFNetworkingOperationFailingURLResponseErrorKey` 301 | The corresponding value is an `NSURLResponse` containing the response of the operation associated with an error. This key is only present in the `AFURLResponseSerializationErrorDomain`. 302 | 303 | `AFNetworkingOperationFailingURLResponseDataErrorKey` 304 | The corresponding value is an `NSData` containing the original data of the operation associated with an error. This key is only present in the `AFURLResponseSerializationErrorDomain`. 305 | */ 306 | extern NSString * const AFNetworkingOperationFailingURLResponseErrorKey; 307 | 308 | extern NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey; 309 | 310 | 311 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // UploadExamples 4 | // 5 | // Created by 刘凡 on 15/1/31. 6 | // Copyright (c) 2015年 joyios. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // UploadExamples 4 | // 5 | // Created by 刘凡 on 15/1/31. 6 | // Copyright (c) 2015年 joyios. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.joyios.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // UploadExamples 4 | // 5 | // Created by 刘凡 on 15/1/31. 6 | // Copyright (c) 2015年 joyios. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // UploadExamples 4 | // 5 | // Created by 刘凡 on 15/1/31. 6 | // Copyright (c) 2015年 joyios. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "AFNetworking.h" 11 | #import "NSMutableURLRequest+Upload.h" 12 | 13 | @interface ViewController () 14 | 15 | @end 16 | 17 | @implementation ViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | // Do any additional setup after loading the view, typically from a nib. 22 | } 23 | 24 | - (void)didReceiveMemoryWarning { 25 | [super didReceiveMemoryWarning]; 26 | // Dispose of any resources that can be recreated. 27 | } 28 | 29 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 30 | [self demo6]; 31 | } 32 | 33 | #pragma mark - AFN Upload Multifiles 34 | // MARK: - AFN AFHTTPRequestOperationManager 上传多个文件,并指定保存在服务器的文件名 35 | - (void)demo6 { 36 | NSURL *url = [NSURL URLWithString:@"http://localhost/post/upload-m.php"]; 37 | 38 | NSArray *fileURLs = @[[[NSBundle mainBundle] URLForResource:@"111" withExtension:nil], 39 | [[NSBundle mainBundle] URLForResource:@"222" withExtension:nil]]; 40 | NSArray *fileNames = @[@"abc.txt", @"bcd.txt"]; 41 | 42 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url fileURLs:fileURLs fileNames:fileNames name:@"userfile"]; 43 | 44 | AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 45 | AFHTTPRequestOperation *op = [manager HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) { 46 | NSLog(@"%@", responseObject); 47 | } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 48 | NSLog(@"%@", error); 49 | }]; 50 | [manager.operationQueue addOperation:op]; 51 | } 52 | 53 | // MARK: - AFN AFHTTPSessionManager 上传多个文件,并指定保存在服务器的文件名 54 | - (void)demo5 { 55 | NSURL *url = [NSURL URLWithString:@"http://localhost/post/upload-m.php"]; 56 | 57 | NSArray *fileURLs = @[[[NSBundle mainBundle] URLForResource:@"111" withExtension:nil], 58 | [[NSBundle mainBundle] URLForResource:@"222" withExtension:nil]]; 59 | NSArray *fileNames = @[@"abc.txt", @"bcd.txt"]; 60 | 61 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url fileURLs:fileURLs fileNames:fileNames name:@"userfile"]; 62 | 63 | AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; 64 | [[manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) { 65 | NSLog(@"%@", responseObject); 66 | }] resume]; 67 | } 68 | 69 | #pragma mark - POST Upload Demo 70 | // MARK: - 上传单个文件,并指定保存在服务器的文件名 71 | - (void)demo4 { 72 | NSURL *url = [NSURL URLWithString:@"http://localhost/post/upload.php"]; 73 | 74 | NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"111" withExtension:nil]; 75 | 76 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url fileURL:fileURL fileName:@"hello.txt" name:@"userfile"]; 77 | 78 | [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 79 | 80 | id result = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL]; 81 | NSLog(@"%@", result); 82 | }] resume]; 83 | } 84 | 85 | // MARK: - 上传单个文件,保存成同名的文件 86 | - (void)demo3 { 87 | NSURL *url = [NSURL URLWithString:@"http://localhost/post/upload.php"]; 88 | 89 | NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"111" withExtension:nil]; 90 | 91 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url fileURL:fileURL name:@"userfile"]; 92 | 93 | [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 94 | 95 | id result = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL]; 96 | NSLog(@"%@", result); 97 | }] resume]; 98 | } 99 | 100 | // MARK: - 上传多个文件,并指定保存在服务器的文件名 101 | - (void)demo2 { 102 | NSURL *url = [NSURL URLWithString:@"http://localhost/post/upload-m.php"]; 103 | 104 | NSArray *fileURLs = @[[[NSBundle mainBundle] URLForResource:@"111" withExtension:nil], 105 | [[NSBundle mainBundle] URLForResource:@"222" withExtension:nil]]; 106 | NSArray *fileNames = @[@"abc.txt", @"bcd.txt"]; 107 | 108 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url fileURLs:fileURLs fileNames:fileNames name:@"userfile"]; 109 | 110 | [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 111 | 112 | id result = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL]; 113 | NSLog(@"%@", result); 114 | }] resume]; 115 | } 116 | 117 | // MARK: - 上传多个文件,保存成同名的文件 118 | - (void)demo1 { 119 | NSURL *url = [NSURL URLWithString:@"http://localhost/post/upload-m.php"]; 120 | 121 | NSArray *fileURLs = @[[[NSBundle mainBundle] URLForResource:@"111" withExtension:nil], 122 | [[NSBundle mainBundle] URLForResource:@"222" withExtension:nil]]; 123 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url fileURLs:fileURLs name:@"userfile"]; 124 | 125 | [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 126 | 127 | id result = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL]; 128 | NSLog(@"%@", result); 129 | }] resume]; 130 | } 131 | 132 | @end 133 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamples/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // UploadExamples 4 | // 5 | // Created by 刘凡 on 15/1/31. 6 | // Copyright (c) 2015年 joyios. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamplesTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.joyios.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /UploadExamples/UploadExamplesTests/UploadExamplesTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // UploadExamplesTests.m 3 | // UploadExamplesTests 4 | // 5 | // Created by 刘凡 on 15/1/31. 6 | // Copyright (c) 2015年 joyios. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface UploadExamplesTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation UploadExamplesTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /UploadRequest/NSMutableURLRequest+Upload.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableURLRequest+Upload.h 3 | // UploadExamples 4 | // 5 | // Created by 刘凡 on 15/1/31. 6 | // Copyright (c) 2015年 joyios. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSMutableURLRequest (Upload) 12 | 13 | /** 14 | * 生成单文件上传的 multipart/form-data 请求 15 | * 16 | * @param URL 负责上传的 url 17 | * @param fileURL 要上传的本地文件 url 18 | * @param name 服务器脚本字段名 19 | * 20 | * @return multipart/form-data POST 请求,保存到服务器的文件名与本地的文件名一致 21 | */ 22 | + (instancetype)requestWithURL:(NSURL *)URL fileURL:(NSURL *)fileURL name:(NSString *)name; 23 | 24 | /** 25 | * 生成单文件上传的 multipart/form-data 请求 26 | * 27 | * @param URL 负责上传的 url 28 | * @param fileURL 要上传的本地文件 url 29 | * @param fileName 要保存在服务器上的文件名 30 | * @param name 服务器脚本字段名 31 | * 32 | * @return multipart/form-data POST 请求 33 | */ 34 | + (instancetype)requestWithURL:(NSURL *)URL fileURL:(NSURL *)fileURL fileName:(NSString *)fileName name:(NSString *)name; 35 | 36 | /** 37 | * 生成多文件上传的 multipart/form-data 请求 38 | * 39 | * @param URL 负责上传的 url 40 | * @param fileURLs 要上传的本地文件 url 数组 41 | * @param name 服务器脚本字段名 42 | * 43 | * @return multipart/form-data POST 请求,保存到服务器的文件名与本地的文件名一致 44 | */ 45 | + (instancetype)requestWithURL:(NSURL *)URL fileURLs:(NSArray *)fileURLs name:(NSString *)name; 46 | 47 | /** 48 | * 生成多文件上传的 multipart/form-data 请求 49 | * 50 | * @param URL 负责上传的 url 51 | * @param fileURLs 要上传的本地文件 url 数组 52 | * @param fileNames 要保存在服务器上的文件名数组 53 | * @param name 服务器脚本字段名 54 | * 55 | * @return multipart/form-data POST 请求 56 | */ 57 | + (instancetype)requestWithURL:(NSURL *)URL fileURLs:(NSArray *)fileURLs fileNames:(NSArray *)fileNames name:(NSString *)name; 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /UploadRequest/NSMutableURLRequest+Upload.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableURLRequest+Upload.m 3 | // UploadExamples 4 | // 5 | // Created by 刘凡 on 15/1/31. 6 | // Copyright (c) 2015年 joyios. All rights reserved. 7 | // 8 | 9 | #import "NSMutableURLRequest+Upload.h" 10 | 11 | @implementation NSMutableURLRequest (Upload) 12 | 13 | + (instancetype)requestWithURL:(NSURL *)URL fileURL:(NSURL *)fileURL name:(NSString *)name { 14 | return [self requestWithURL:URL fileURLs:@[fileURL] name:name]; 15 | } 16 | 17 | + (instancetype)requestWithURL:(NSURL *)URL fileURL:(NSURL *)fileURL fileName:(NSString *)fileName name:(NSString *)name { 18 | return [self requestWithURL:URL fileURLs:@[fileURL] fileNames:@[fileName] name:name]; 19 | } 20 | 21 | + (instancetype)requestWithURL:(NSURL *)URL fileURLs:(NSArray *)fileURLs name:(NSString *)name { 22 | 23 | NSMutableArray *fileNames = [NSMutableArray arrayWithCapacity:fileURLs.count]; 24 | [fileURLs enumerateObjectsUsingBlock:^(NSURL *fileURL, NSUInteger idx, BOOL *stop) { 25 | [fileNames addObject:fileURL.path.lastPathComponent]; 26 | }]; 27 | 28 | return [self requestWithURL:URL fileURLs:fileURLs fileNames:fileNames name:name]; 29 | } 30 | 31 | + (instancetype)requestWithURL:(NSURL *)URL fileURLs:(NSArray *)fileURLs fileNames:(NSArray *)fileNames name:(NSString *)name { 32 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL]; 33 | 34 | request.HTTPMethod = @"POST"; 35 | 36 | NSMutableData *data = [NSMutableData data]; 37 | NSString *boundary = multipartFormBoundary(); 38 | 39 | if (fileURLs.count > 1) { 40 | name = [name stringByAppendingString:@"[]"]; 41 | } 42 | 43 | [fileURLs enumerateObjectsUsingBlock:^(NSURL *fileURL, NSUInteger idx, BOOL *stop) { 44 | NSString *bodyStr = [NSString stringWithFormat:@"\r\n--%@\r\n", boundary]; 45 | [data appendData:[bodyStr dataUsingEncoding:NSUTF8StringEncoding]]; 46 | 47 | NSString *fileName = fileNames[idx]; 48 | bodyStr = [NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\" \r\n", name, fileName]; 49 | [data appendData:[bodyStr dataUsingEncoding:NSUTF8StringEncoding]]; 50 | [data appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; 51 | 52 | [data appendData:[NSData dataWithContentsOfURL:fileURL]]; 53 | 54 | [data appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; 55 | }]; 56 | 57 | NSString *tailStr = [NSString stringWithFormat:@"--%@--\r\n", boundary]; 58 | [data appendData:[tailStr dataUsingEncoding:NSUTF8StringEncoding]]; 59 | 60 | request.HTTPBody = data; 61 | 62 | NSString *headerString = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary]; 63 | [request setValue:headerString forHTTPHeaderField:@"Content-Type"]; 64 | 65 | return request; 66 | } 67 | 68 | static NSString * multipartFormBoundary() { 69 | return [NSString stringWithFormat:@"Boundary+%08X%08X", arc4random(), arc4random()]; 70 | } 71 | 72 | @end 73 | --------------------------------------------------------------------------------