分类 网络 下的文章

使用NSURLConnection下载

蛋疼的是,一个213M的文件内存峰值能到173M....
参考了这两个文章:http://blog.csdn.net/fightper/article/details/20036203
http://blog.csdn.net/lengshengren/article/details/12905697/

//
//  ViewController.swift
//  下载
//
//  Created by zhang on 16/2/28.
//  Copyright © 2016年 jin. All rights reserved.
//
/**

NSURLConnection存在的问题,iOS2.0就有了。 专门用来负责网络数据的传输,已经有10多年的历史

特点:
- 处理简单的网络操作,非常简单
- 但是处理复杂的网络操作,就非常繁琐
ASI&AFN

iOS 5.0以前,网络的下载是一个黑暗的时代
*** iOS5.0以前 通过代理的方式来处理网络数据

存在的问题:
1.下载的过程中,没有”进度的跟进“ -- 用户的体验不好
2.存在内存的峰值


解决进度跟进的问题
解决办法:通过代理的方式来处理网络数据

代理还是出现峰值, 是因为全部接受完了,再去写入
解决办法,接收到一点,写一点
//    NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(click) userInfo:nil repeats:YES];
////    NSDefaultRunLoopMode : 默认的运行循环模式。 处理的优先级比NSRunLoopCommonModes低
////    NSRunLoopCommonModes : 通用的模式,在用户拖动屏幕的时候同样执行
//    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

NSURLConnection的代理,默认是在主线程运行的
需要把他的代理 移到子线程执行

下载这个任务 本身还在主线程。 所有导致进度条的更新非常卡
主线程现在在做两件事,1. 下载 2.更新进度条

NSURLConnection问题:
1. 做复杂的网络操作,需要使用代理来实现。 比如下载大文件
2. 默认下载任务在主线程工作。
3. 默认这个任务的代理也是在主线程
4. 如果添加到子线程去执行,需要主动启动运行循环
5. 只提供开始和取消。 不支持暂停。

*/



import UIKit

class ViewController: UIViewController,NSURLConnectionDataDelegate {

    @IBOutlet weak var progress: UIProgressView!
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        /**
         这样执行的话,是在主线程执行的
        let connection = NSURLConnection(request: request, delegate: self ,startImmediately: false)
        connection?.scheduleInRunLoop(NSRunLoop.mainRunLoop(), forMode: NSRunLoopCommonModes)
        connection?.start()
        */
        // 把网络请求放到子线程
        NSOperationQueue().addOperationWithBlock { () -> Void in
            let url = NSURL(string: "http://localhost/1.mp4")
            let request = NSMutableURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.ReloadIgnoringCacheData, timeoutInterval: 10)
            // 这个文件比较大
            let queue = NSOperationQueue()
            queue.maxConcurrentOperationCount = 1
            let connection = NSURLConnection(request: request, delegate: self ,startImmediately: false)
            // 设置代理执行的线程在子进程
            connection?.setDelegateQueue(queue)
            // 开始
            connection?.start()

        }
    }
    var fileSize:Int64 = 0
    var currentSize:Int64 = 0
    // 接受请求
    func connection(connection: NSURLConnection, didReceiveResponse response: NSURLResponse) {
        /**
            response里面的信息
            { URL: http://localhost/1.mp4 } { status code: 200, headers {
                "Accept-Ranges" = bytes;
                Connection = "Keep-Alive";
                "Content-Length" = 213811516;
                Date = "Sun, 28 Feb 2016 02:22:25 GMT";
                Etag = "\"cbe813c-528c686a2b8c0\"";
                "Keep-Alive" = "timeout=5, max=100";
                "Last-Modified" = "Thu, 07 Jan 2016 23:06:51 GMT";
                Server = "Apache/2.4.18 (Unix) OpenSSL/1.0.2f PHP/7.0.2 mod_perl/2.0.8-dev Perl/v5.16.3";
        } }
        */
        // 获得文件的总长度
        self.fileSize = response.expectedContentLength
        self.currentSize = 0
        // 避免重复写入的问题
        try? NSFileManager.defaultManager().removeItemAtPath(self.path)
    }
    // 定义保存文件的路径
    let path = "/Users/zhang/Desktop/123.mp4"
    // 接受数据
    func connection(connection: NSURLConnection, didReceiveData data: NSData) {
        // 获得文件资源文件句柄
        let handle = NSFileHandle(forWritingAtPath: path)
        // 文件不存在的时候使用nsdata进行写入
        if handle == nil
        {
            data.writeToFile(path, atomically: true)
        }
        else
        {
            // 移动指向到文件尾部,避免每次写入都吧文件替换了
            handle?.seekToEndOfFile()
            // 写入
            handle?.writeData(data)
        }
        // 一定要关闭!!!
        handle?.closeFile()
        // 当前已经下载的文件的大小,去主线程更新ui
        NSOperationQueue.mainQueue().addOperationWithBlock { () -> Void in
            self.currentSize += data.length
            self.progress.progress = Float(Float64(self.currentSize) / Float64(self.fileSize))
        }
    }
    func connectionDidFinishLoading(connection: NSURLConnection) {
        print("连接完成")
    }
    func connection(connection: NSURLConnection, didFailWithError error: NSError) {
        print("错误啦")
    }

}

swift使用cookie

//
//  ViewController.swift
//  加密
//
//  Created by admin on 16/2/27.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    // 发送下请求,服务器那边有写cookie的代码
    @IBAction func sendRequest(sender: AnyObject) {
        let url = NSURL(string: "http://test.com/login2.php")
        let request = NSMutableURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.ReloadIgnoringCacheData, timeoutInterval: 10)
        let postData = "username=zhangsan&password=zhang"
        request.HTTPMethod = "post"
//        request.HTTPBody = postData.dataUsingEncoding(NSUTF8StringEncoding)
        // 请求会自动带上cookie
        NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue()) { (response:NSURLResponse?, data:NSData?, error:NSError?) -> Void in
            print(try? NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments))
        }
    }
    @IBAction func readCookie(sender: AnyObject) {
        // 第一次读取是没有任何输出的,发送请求之后久能取到下面的值了,因为服务器设置了cookie
        for cookie in NSHTTPCookieStorage.sharedHTTPCookieStorage().cookies!
        {
            if(cookie.name == "userName")
            {
                print("用户名为\(cookie.value)")
            }
            if(cookie.name == "userPassword")
            {
                print("密码为\(cookie.value)")
            }
        }
    }
}

base加密解密

//
//  ViewController.swift
//  base64
//
//  Created by zhang on 16/2/26.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var name: UITextField!
    @IBOutlet weak var password: UITextField!
    @IBOutlet weak var messageLable: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
        let userDefault = NSUserDefaults.standardUserDefaults()
        let userName = userDefault.valueForKey("username")
        print(userName)
        if userName != nil
        {
            self.name.text = self.decode(userName as! String)
            let password = userDefault.valueForKey("password")
            self.password.text = self.decode(password as! String)
        }
    }

    @IBAction func login(sender: AnyObject) {
        let username = self.name.text
        let password = self.password.text
        let url = NSURL(string: "http://localhost/login.php")
        let request = NSMutableURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.ReloadIgnoringCacheData, timeoutInterval: 10)
        request.HTTPMethod = "post"
        let dataString = "username=\(self.encode(username!))&password=\(self.encode(password!))"
        print(dataString)
        request.HTTPBody = dataString.dataUsingEncoding(NSUTF8StringEncoding)
        NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue()) { (response:NSURLResponse?, data:NSData?, error:NSError?) -> Void in
            let json:AnyObject? = try? NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.AllowFragments)
            let userId:Int! = json?.valueForKey("userId") as! Int
            var str = ""
            if userId != nil && userId > 0
            {
                str = "登陆成功"
                let userDefault = NSUserDefaults.standardUserDefaults()
                userDefault.setObject(self.encode(username!), forKey: "username")
                userDefault.setObject(self.encode(password!), forKey: "password")
                userDefault.synchronize()
            }
            else
            {
                str = "登陆失败"
            }
            NSOperationQueue.mainQueue().addOperationWithBlock({ [weak self,str] () -> Void in
                self!.messageLable.text = str
            })
        }
    }
    func encode(str:String)->String
    {
        // 字符串转换成d
        let data = str.dataUsingEncoding(NSUTF8StringEncoding)
        let encodeStr = data?.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding64CharacterLineLength)
        return encodeStr!
    }
    func decode(str:String)->String
    {
        let decode = NSData(base64EncodedString: str, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)
        return String(data: decode!, encoding: NSUTF8StringEncoding)!
    }
}

swift直接传输json字串

客户端

//
//  ViewController.swift
//  http请求
//
//  Created by admin on 16/2/26.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.sendJSON()
    }
    func sendJSON()
    {
        let urlStr = "http://test.com/postjson.php"
        let url = NSURL(string: urlStr.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)
        let request = NSMutableURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.ReloadIgnoringCacheData, timeoutInterval: 10)
        let jsonData = ["name":"jin","age":18]
        // 检查数据类型是否能转换成json
        if NSJSONSerialization.isValidJSONObject(jsonData) == false
        {
            print("格式错误")
            exit(1)
        }
        let sendData = try? NSJSONSerialization.dataWithJSONObject(jsonData, options: NSJSONWritingOptions.PrettyPrinted)
        // 设置类型以及数据
        request.HTTPMethod = "post"
        request.HTTPBody = sendData
        NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue()) { (response:NSURLResponse?, data:NSData?, error:NSError?) -> Void in
            let jsonData:AnyObject? = try? NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)
            print(jsonData)
        }
    }
}

服务器

header('Content-Type:text/plain;charset=utf-8');

$json = file_get_contents('php://input');
// 反序列化JSON
$obj = json_decode($json, TRUE ); 

// 打印对象明细信息
echo json_encode($obj);

swift实现http上传

//
//  ViewController.swift
//  http请求
//
//  Created by admin on 16/2/26.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.uploadFile()
    }
    func uploadFile()
    {
        let urlStr = "http://test.com/upload.php"
        let url = NSURL(string: urlStr.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)

        var request = NSMutableURLRequest(URL: url!, cachePolicy: NSURLRequestCachePolicy.ReloadIgnoringCacheData, timeoutInterval: 10)
        // 设置上传文件所需要的信息
        self.setUploadRequest(&request,filePath: NSBundle.mainBundle().pathForResource("2.jpg", ofType: nil)!)

        NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue()) { (response: NSURLResponse?, data:NSData?, error:NSError?) -> Void in
            let json:AnyObject? = try? NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)
            print(json)
        }
    }
    // 设置上传文件的头
    func setUploadRequest(inout request:NSMutableURLRequest,filePath:String)->NSMutableURLRequest
    {
        let seperator = "jin"
        // 设置请求类型
        request.HTTPMethod = "post"
        // 设置http头
        // Content-Type multipart/form-data; boundary(分隔符)=(可以随便写, 但是不能有中文)
        let header = "multipart/form-data; boundary=\(seperator)"
        request.setValue(header, forHTTPHeaderField: "Content-Type")

        // 拼接数据
        let bodyData = NSMutableData()
        // \r\n--(可以随便写, 但是不能有中文)\r\n
        var str = "\r\n--\(seperator)\r\n"
        bodyData.appendData(str.dataUsingEncoding(NSUTF8StringEncoding)!)

        // Content-Length(文件的大小)    这个不用写
        // Content-Disposition: form-data; name="userfile(php脚本中用来读取文件的字段)"; filename="demo.json(要保存到服务器的文件名)"\r\n
        str = "Content-Disposition: form-data; name=\"uploadFile\"; filename=\"newFile.jpg\"\r\n"
        bodyData.appendData(str.dataUsingEncoding(NSUTF8StringEncoding)!)

        // Content-Type: application/octet-stream(上传文件的类型)\r\n\r\n
        str = "Content-Type: application/octet-stream\r\n\r\n"
        bodyData.appendData(str.dataUsingEncoding(NSUTF8StringEncoding)!)

        // 要上传的文件的二进制流
        let fileData = NSData(contentsOfFile: filePath)
        bodyData.appendData(fileData!)

        // \r\n--(可以随便写, 但是不能有中文)--\r\n
        str = "\r\n--\(seperator)--\r\n"
        bodyData.appendData(str.dataUsingEncoding(NSUTF8StringEncoding)!)
        request.HTTPBody = bodyData
        return request
    }
}