NSURLConnection

使用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 - 
/**
 * 解析到某个元素的结尾(比如解析)
 */
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
//    NSLog(@"didEndElement - %@", elementName);
}

/**
 * 解析到某个元素的开头(比如解析)
 */
- (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 () 
@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 - 
- (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 () 
@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 - 
/**
 * 接收到响应的时候:创建一个空的文件
 */
- (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 () 
/** 输出流对象 */
@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 - 
- (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 () 
/** 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 - 
- (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

你可能感兴趣的:(NSURLConnection)