使用NSURLConnection发送请求的步骤很简单
(1)创建一个NSURL对象,设置请求路径
(2)传入NSURL创建一个NSURLRequest对象,设置请求头和请求体
(3)使用NSURLConnection发送请求
1.GET请求
// 0.请求路径
NSString *urlStr = @"http://120.25.226.186:32812/login2?username=小码哥&pwd=520it";
// 将中文URL进行转码
urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:urlStr];
// 1.创建请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 2.发送请求
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// 3.解析服务器返回的数据(解析成字符串)
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", string);
}];
2.POST请求
// 1.请求路径
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"];
// 2.创建请求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// 更改请求方法
request.HTTPMethod = @"POST";
// 设置请求体
request.HTTPBody = [@"username=520it&pwd=520it" dataUsingEncoding:NSUTF8StringEncoding];
// 设置超时(5秒后超时)
request.timeoutInterval = 5;
// 设置请求头
// [request setValue:@"iOS 9.0" forHTTPHeaderField:@"User-Agent"];
// 3.发送请求
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (connectionError) { // 比如请求超时
NSLog(@"----请求失败");
} else {
NSLog(@"------%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}
}];
3.图片上传
#define XMGBoundary @"520it"
#define XMGEncode(string) [string dataUsingEncoding:NSUTF8StringEncoding]
#define XMGNewLine [@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 创建请求
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/upload"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
// 设置请求头(告诉告诉服务器,这是一个文件上传的请求)
[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", XMGBoundary] forHTTPHeaderField:@"Content-Type"];
// 设置请求体
NSMutableData *body = [NSMutableData data];
// 文件参数
/*
--分割线\r\n
Content-Disposition: form-data; name="参数名"; filename="文件名"\r\n
Content-Type: 文件的MIMEType\r\n
\r\n
文件数据
\r\n
*/
// 分割线
[body appendData:XMGEncode(@"--")];
[body appendData:XMGEncode(XMGBoundary)];
[body appendData:XMGNewLine];
// 文件参数名
[body appendData:XMGEncode([NSString stringWithFormat:@"Content-Disposition: form-data; name=\"file\"; filename=\"test.png\""])];
[body appendData:XMGNewLine];
// 文件的类型
[body appendData:XMGEncode([NSString stringWithFormat:@"Content-Type: image/png"])];
[body appendData:XMGNewLine];
// 文件数据
[body appendData:XMGNewLine];
// UIImageJPEGRepresentation(<#UIImage *image#>, <#CGFloat compressionQuality#>)
UIImage *image = [UIImage imageNamed:@"placeholder"];
[body appendData:UIImagePNGRepresentation(image)];
// [body appendData:[NSData dataWithContentsOfFile:@"/Users/xiaomage/Desktop/test.png"]];
[body appendData:XMGNewLine];
// 非文件参数
/*
--分割线\r\n
Content-Disposition: form-data; name="参数名"\r\n
\r\n
参数值
\r\n
*/
// 分割线
[body appendData:XMGEncode(@"--")];
[body appendData:XMGEncode(XMGBoundary)];
[body appendData:XMGNewLine];
// 参数名
[body appendData:XMGEncode([NSString stringWithFormat:@"Content-Disposition: form-data; name=\"username\""])];
[body appendData:XMGNewLine];
// 参数值
[body appendData:XMGNewLine];
[body appendData:XMGEncode(@"jack")];
[body appendData:XMGNewLine];
// 结束标记
/*
--分割线--\r\n
*/
[body appendData:XMGEncode(@"--")];
[body appendData:XMGEncode(XMGBoundary)];
[body appendData:XMGEncode(@"--")];
[body appendData:XMGNewLine];
request.HTTPBody = body;
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSLog(@"%@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);
}];
}
@end
4.解析Json
// 解析JSON
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
5.解析XML
// 创建XML解析器
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
// 设置代理
parser.delegate = self;
// 开始解析XML
[parser parse];
#pragma mark - <NSXMLParserDelegate>
/**
* 解析到某个元素的结尾(比如解析</videos>)
*/
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
// NSLog(@"didEndElement - %@", elementName);
}
/**
* 解析到某个元素的开头(比如解析<videos>)
*/
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:@"videos"]) return;
// XMGVideo *video = [[XMGVideo alloc] init];
// video.keyValues = attributeDict;
XMGVideo *video = [XMGVideo objectWithKeyValues:attributeDict];
[self.videos addObject:video];
}
/**
* 开始解析XML文档
*/
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
// NSLog(@"parserDidStartDocument");
}
/**
* 解析完毕
*/
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
// NSLog(@"parserDidEndDocument");
}
6.用GDataXML(第三方)解析XML
// 加载整个文档
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:data options:0 error:nil];
// 获得所有video元素
NSArray *elements = [doc.rootElement elementsForName:@"video"];
for (GDataXMLElement *ele in elements) {
XMGVideo *video = [[XMGVideo alloc] init];
video.name = [ele attributeForName:@"name"].stringValue;
video.url = [ele attributeForName:@"url"].stringValue;
video.image = [ele attributeForName:@"image"].stringValue;
video.length = [ele attributeForName:@"length"].stringValue.integerValue;
[self.videos addObject:video];
}
7.小文件下载
#import "ViewController.h"
@interface ViewController () <NSURLConnectionDataDelegate>
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
/** 文件数据 */
@property (nonatomic, strong) NSMutableData *fileData;
/** 文件的总长度 */
@property (nonatomic, assign) NSInteger contentLength;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_15.mp4"];
[NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:url] delegate:self];
}
#pragma mark - <NSURLConnectionDataDelegate>
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response
{
self.contentLength = [response.allHeaderFields[@"Content-Length"] integerValue];
self.fileData = [NSMutableData data];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.fileData appendData:data];
CGFloat progress = 1.0 * self.fileData.length / self.contentLength;
NSLog(@"已下载:%.2f%%", (progress) * 100);
self.progressView.progress = progress;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"下载完毕");
// 将文件写入沙盒中
// 缓存文件夹
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
// 文件路径
NSString *file = [caches stringByAppendingPathComponent:@"minion_15.mp4"];
// 写入数据
[self.fileData writeToFile:file atomically:YES];
self.fileData = nil;
}
- (void)connDownload
{
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_15.png"];
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:url] queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSLog(@"%zd", data.length);
}];
}
- (void)dataDownlaod
{
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_15.png"];
NSData *data = [NSData dataWithContentsOfURL:url];
NSLog(@"%zd", data.length);
}
8.大文件下载
#import "ViewController.h"
#define XMGFile [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"minion_15.mp4"]
@interface ViewController () <NSURLConnectionDataDelegate>
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
/** 文件的总长度 */
@property (nonatomic, assign) NSInteger contentLength;
/** 当前下载的总长度 */
@property (nonatomic, assign) NSInteger currentLength;
/** 文件句柄对象 */
@property (nonatomic, strong) NSFileHandle *handle;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_15.mp4"];
[NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:url] delegate:self];
}
#pragma mark - <NSURLConnectionDataDelegate>
/**
* 接收到响应的时候:创建一个空的文件
*/
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response
{
// 获得文件的总长度
self.contentLength = [response.allHeaderFields[@"Content-Length"] integerValue];
// 创建一个空的文件
[[NSFileManager defaultManager] createFileAtPath:XMGFile contents:nil attributes:nil];
// 创建文件句柄
self.handle = [NSFileHandle fileHandleForWritingAtPath:XMGFile];
}
/**
* 接收到具体数据:马上把数据写入一开始创建好的文件
*/
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// 指定数据的写入位置 -- 文件内容的最后面
[self.handle seekToEndOfFile];
// 写入数据
[self.handle writeData:data];
// 拼接总长度
self.currentLength += data.length;
// 进度
self.progressView.progress = 1.0 * self.currentLength / self.contentLength;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// 关闭handle
[self.handle closeFile];
self.handle = nil;
// 清空长度
self.currentLength = 0;
}
9.用ZipArchive(第三方)压缩和解压缩
#import "ViewController.h"
#import "Main.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[Main unzipFileAtPath:@"/Users/xiaomage/Desktop/TestAbc.zip" toDestination:@"/Users/xiaomage/Desktop"];
}
- (void)createZipFile2
{
[Main createZipFileAtPath:@"/Users/xiaomage/Desktop/TestAbc.zip" withContentsOfDirectory:@"/Users/xiaomage/Desktop/Test"];
}
- (void)createZipFile
{
NSArray *paths = @[
@"/Users/xiaomage/Desktop/Test/Snip20150713_276.png",
@"/Users/xiaomage/Desktop/Test/Snip20150713_299.png",
@"/Users/xiaomage/Desktop/Test/Snip20150713_500.png"
];
[Main createZipFileAtPath:@"/Users/xiaomage/Desktop/TestAbc.zip" withFilesAtPaths:paths];
}
10.NSMutableURLRequest
NSMutableURLRequest是NSURLRequest的子类,常用方法有
// 设置请求超时等待时间(超过这个时间就算超时,请求失败)
-(void)setTimeoutInterval:(NSTimeInterval)seconds;
// 设置请求方法(比如GET和POST)
-(void)setHTTPMethod:(NSString*)method;
// 设置请求体
-(void)setHTTPBody:(NSData*)data;
// 设置请求头
-(void)setValue:(NSString*)value forHTTPHeaderField:(NSString*)field;
11.NSOutputStream方式大文件下载
#import "ViewController.h"
@interface ViewController () <NSURLConnectionDataDelegate>
/** 输出流对象 */
@property (nonatomic, strong) NSOutputStream *stream;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"]] delegate:self];
}
#pragma mark - <NSURLConnectionDataDelegate>
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// response.suggestedFilename : 服务器那边的文件名
// 文件路径
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSString *file = [caches stringByAppendingPathComponent:response.suggestedFilename];
NSLog(@"%@", file);
// 利用NSOutputStream往Path中写入数据(append为YES的话,每次写入都是追加到文件尾部)
self.stream = [[NSOutputStream alloc] initToFileAtPath:file append:YES];
// 打开流(如果文件不存在,会自动创建)
[self.stream open];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.stream write:[data bytes] maxLength:data.length];
NSLog(@"didReceiveData-------");
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[self.stream close];
NSLog(@"-------");
}
12.NSURLConnection与RunLoop
NSURLConnection发出请求,等待接收服务器一点一点返回的数据,需要有一个运行循环等待服务器给NSURLConnection数据,也就是说NSURLConnection是在RunLoop中接收服务器返回的数据
NSURLConnection内部会关联当前线程对应的RunLoop,不断的给当前线程的RunLoop传递消息,RunLoop接收到Source进行处理
NSURLConnection在子线程发送请求时,子线程的RunLoop默认是不启动的,所以接受不到服务器返回的数据。在主线程中,主线程的RunLoop是默认启动的,所以可以接受服务器返回的数据
要想NSURLConnection在子线程发送请求,可以接收到服务器返回的数据,要开启子线程的RunLoop,具体方法如下,有两种方法实现:
#import "ViewController.h"
@interface ViewController () <NSURLConnectionDataDelegate>
/** runLoop */
@property (nonatomic, assign) CFRunLoopRef runLoop;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSURLConnection *conn = [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_01.png"]] delegate:self];
// 决定代理方法在哪个队列中执行
[conn setDelegateQueue:[[NSOperationQueue alloc] init]];
// 方法一
// 启动子线程的runLoop
// [[NSRunLoop currentRunLoop] run];
// 方法二
self.runLoop = CFRunLoopGetCurrent();
// 启动runLoop
CFRunLoopRun();
});
}
#pragma mark - <NSURLConnectionDataDelegate>
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(@"didReceiveResponse----%@", [NSThread currentThread]);
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(@"didReceiveData----%@", [NSThread currentThread]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"connectionDidFinishLoading----%@", [NSThread currentThread]);
// 停止RunLoop
CFRunLoopStop(self.runLoop);
}
@end