编辑代码

调用成功后返回的数据
{
    "refresh_token":"25.b55feld287227ca97aab219bb249b8ab.315360000.1798284651.282335-8574074",
    "expires_in": 2592000,
    "scope": "public wise adapt",
    "session key": "9mzdDZXu3dENdFZQurfg0Vz8s1gSgvvOAUebNFzyzcpQ5EnbxbF+ hfG9DQkpUVQdh4p6HbcAiz5RmuBAjalJJGgIdJI",
    "access token":"24.6c5e1ff107f0e8bcef8c46d3424a0e78.2592000.1485516651282335-8574074",
    "session secret": "dfac94a3489fe9fca7c3221cbf7525ff"
}
如果出错,则返回:
{
    "error": "invalid client",
    "error description": "unknown client id"
}
在获得 access token 后,可以调用相关功能的 API 来完成该功能,如车型识别能力。 
#encoding;utf-8 
import requests

#client_id 为官网获取的AK, elient secret 为官网获取的 SK
host='https://aip,baidubce,com/oauth/2,0/token?grant_type-client cradentialeeclient_id-【官网获取的AK】sclient_secret-【官网获取的 sK】'
reeponse … requests,get (hest) 
If renponees:
   print (rosponse,jeon())



表6-1参数详情
# encoding:utf-8
import requests
import base64
''''
车型识别
''''
request_url … "https://aip.baidubce.com/rest/2.0/Lmage-clasnify/v1/car"
#二进制方式打开图片文件
f = open('(本地文件)','rb')
img = base64.b64encode(f.read())


params =("image":img,"top_num":5)
access token ='[调用鉴权接口获取的 token]'
request_url = request_url + "?access_token=" + access_token
headers = ('content-type': 'application/x-www-form-urlencoded')
response = requests.post(request_url, data=params, headers-headers) 
if response:
print (response.json())
返回的 JSON 数据:
{
    "log id": 4086212218842203806,
    "location_result":{
        "width": 447,
        "top":226,
        "height": 209,
        "left":188
},
"result": [{
    "baike_info":{
    "baike_url":"http://baike.baidu.cam/item/%E5%B8%83%E5%8A%A0%E8%BF%AAChiron/20419512",
    "description":"布加迪Chiron是法国跑车品牌布加迪出品的豪华超跑车.配置四涡轮增压发动机,420 公里每小时,有 23 种颜色的选择,售价高达 260 万美元."
},
    "score": 0.98793351650238,
    "name":"布加迪Chiron",
    "year":"无年份信息"
},
{
    "score": 0.0021970034576952,
    "name":"奥迪RS5",
    "year":"2011-2017"
},
{
    "score": 0.0021096928976476,
    "name":"奥迪RS4""year":"无年份信息"
    },
{
    "score": 0.0015581247862428,
    "name":"奥迪RS7""year":"2014-2016"
    },
{
    "score": 0.00082337751518935,
    "name":"布加迪威航""year":"2004-2015"
    }],
"color result":"颜色无法识别"
}

6.1.2数据接口与JSON
下面是一个简单的例子:
{
    "Name": "Li Tao","Profession":"Teacher","Age":20,
    "Email":"1509033925@163.com","Friends": ["Zhang San","Li si"]
}


{"TeamName":"ios-Orange-Team","Teacher":"Chen Zhifeng","Students":[
{ "Name": "Zhang Bo", "Hometown":"Xinxiang"},
{"Name":" Chang Wenxiang ","Hometown":"Yancheng"},
{"Name":" Hu Yinting","Hometown":"Suzhou"}

{
    "coord":("lon":-0.13,"lat":51.51),
    "weather":[{"id":300,"main":"Drizzle","description":"lightintensity drizzle","icon":"09d"}],
    "base" : "stations",
    "main":{
    "temp":280.32,"pressure":1012,"humidity":81,
    "temp_min":279.15,
    "temp_max":281.15
    },
    "visibility":10000,
    "wind":("speed":4.1,"deg":80),
    "clouds":{"all":90},
    "dt":1485789600,
    "sys":{
        "type":1,
        "id":5091,
        "message":0.0103,
        "country":"GB",
        "sunrise":1485762037,
        "sunset":1485794875
    },
    "id":2643743,
    "name":"London",
    "cod":200
}

6.1.3数据JSON解析实例
安装:npminstall json-server-g。mock.js 安装:npm install mockjs -g。
安装完成后,编写一个 myjson.js 文件,生成1000组数据。
# myjson.js

module.exports = function() {
var data = { users: [] }
// Create 1000 users
for (var i = 0; i< 1000; i++) {
data.users.push({ id: i, name: 'user' + i })
}
return data
}


浏览器访问自建的MOCK服务器

# news.js
let Mock = require('mockjs'); 
let Random=Mock.Random;
  module.exports = function() {
    var data ={
        news:[]
    };
ar images = [1,2,3].map(x=>Random.image('200x100’, Random.color(),Random.word(2,6)));
    for (var i = 0; i< 100; i++) {
    var content =Random.cparagraph(0,10); 
    data.news.push({
        id:i,
        title: Random.cword(8,20), 
        desc: content.substr(0,40), 
        tag: Random.cword(2,6),
        views: Random.integer(100,5000),
        images: images.slice(0,Random.integer(1,3))
    })
    return data
}

在Playground中访问自建MOCK服务器

import uikit
import Foundation

//url为NOCRMOCK 服务器的网址
if let url = URL(string: "http://localhost:3004/news"){
    RISession.shared.dataTask(with: url) { (data, response, error)
    if error != nil {
        print ("Network errors")
        else {
            let rs = String(data: data!, encoding: String.Encoding utf8)! 
            print(rs)
            if let json = try? JsONserialization jsonObject(with: data!,ogtions:.allonfragments) {
                print(json)
            }
        }
    }
    .resume()
}
fune sessionGetData(){
    //创建 URL 对象
    let urlstring -"http://www.tuling123.com/" 
    let url surl(stringiurlstring)
    //创建请求对象
    let request = URLRequest(url: url!)

    let session = URLSession.shared
    let dataTask = session.dataTask(with: request,
    completionHandler: {(data, response, error) -> Void in
    if error != nill{
        print(error.debugDescription)
    }else{
        let str - String(data: data!, encoding:tring.Encoding.utf8)
        print(str!)
    }
}) as URLSessionTask
// 使用 resume 方法启动任务 
dataTask.resume ()
}
fune sessionDownloadImage(){
     // 下载地址
    let url = URL(string: "http://hangge.com/blog/images/logo.png")
    //请求
    let request = URLRequest(url: url!)
    let session = URLSession.shared
    // 下载任务
    let downloadTask = session.downloadTask(with: request,
completionHandler: {
(location:URL?, response:URLResponse?, error:Error?)
-> Void in
         //输出下载文件原来的存放目录
         print("location:\(String(describing: location))")
         //location 位置转换
         let locationPath = location? path
         // 获取当前时间 
         let now = NSDate() 
         //当前时间的时间截
         let timeInterval:TimeInterval = now.timeIntervalSince1970
         let timeStamp = String(timeInterval)
         //拷贝到用户目录
         let documents:String = NSHomeDirectory() + "/Documents/\
(timeStamp).png"
         //创建文件管理器
         let fileManager = FileManager.default
         try! fileManager.moveItem(atPath: locationPath!, topath:
documents)
         print("new location:\(documents)")
     })
     //使用resume方法启动任务 
     downloadTask.resume()
}

$ sudo apachectl start | stop | restart
#LoadModule php5_module libexec/apache2/libphp5.so
$ sudo cp /etc/php.ini.default /etc/php.ini
<?php
phpinfo();
?>

<?php
/** php 接收流文件
* @param String $file接收后保存的文件名
* @return boolean
*/
function receiveStreamFile($receiveFile){
    $streamData = isset($GLOBALS['HTTP_RAW_POST_DATA'])? $GLOBALS['HTTP_
RAW_POST_DATA'] :'';
    if(empty($streamData)){
        $streamData = file_get_contents('php://input');
        }
    if($streamData!=''){
        $ret = file_put_contents($receiveFile, $streamData, true);
    }else{
        $ret = false;
    }
    return $ret;
}
//定义服务器存储路径和文件名
$receiveFile = $_SERVER["DOCUMENT_ROOT"]."/uploadFiles/swift.png"; 
echo $receiveFile;
$ret = receiveStreamFile($receiveFile);
echo json_encode(array('success'=>(bool)$ret));
?>

func sessionUploadPhp(){
    //上传地址
    let url = URL(string: “http://localhost/uploadSwift.php")
    //1.创建会话对象
    let session = URLSession.shared
    // 请求 
    var request = URLRequest(url:url!, cachePolicy: .reloadIgnoringCacheData) 
    request.httpMethod = "POST"
    // 上传数据流 
    let fileImage = Bundle.main.path(forResource: "bee1", ofType: "png") 
    let imgData = try! Data(contentsOf: URL(fileURLWithPath: fileImage!))
    let uploadTask = session.uploadTask(with: request as URLRequest, from: 
ingData) {
        (data:Data?, response:URLResponse?, error:Error?) -> Void in
        // 上传完毕后
        if error != nill {
            print(error!)
        }else{
        let str = String(data: data!, encoding: String.Encoding.utf8) 
        print("上传完毕: \(String(describing: str))")
        }
    }
    //使用 resume 方法启动任务 
    uploadTask.resume()
}

import UIKit
import Foundation
let API_Key = "EIpAlhdD7i5152EsiNqpUOF_"
let Secret_Key = "p8EZWg4agjDOxABmKvBYSNyZ1YzGFgb_"
let token_host = "https://aip.baidubce.com/oauth/2.0/token?grant_
type=client_credentials&client_id=\(API_Key)&client_secret=\(Secret_Key)"
var access_token = ""
var expires_in : Int32 = 0
if let url = URL(string: token host){
    URLSession.shared.dataTask(with: url) { (data, response, error) in
        if error != nil {
            print ("network error")
        }
        else {
            if let json = try? JSONSerialization.jsonObject(with: data!,
options: .allowFragments) as? [String :Any] {
                    access_token = json["access token"] as! String 
                    expires_in = json["expires in"l as! Int32 
                    print("--------access_token------") 
                    print(access_token)
                    print("--------expires_time------") 
                    print(expires in)
                }
        }
    }
    .resume ()
}
else {
    print("url error")
}

//以文本或者二进制方式读入源程序文件的 Loader 
public struct Loader {
    static func readTxt(file url:URL) -> string? {
        do {
            let source = try String(contentsOf: url) 
            return source
        }
        catch {
            return nil
        }
    }
static func readBin(file url:URL) -> Data? {
        do {
            let data = try Data(contentsOf: url) 
            return data
        }
        catch {
            return nil
        }
}

//Resources中的文件,并把路径转化为URL
let path = Bundle.main.path(forResource: "qrcar.jpg", ofType: nil) 
let url = URL(fileURLWithPath: path!)

let data = Loader.readBin(file: url)

if(data == nil) {
    print("File failed to load")
}

let data_base64_str = data?.base64EncodedString() 
let data_base64 = data?.base64EncodedData()

access_token ="24.2ec96a68f74a8429b0f07869929413ae.2592000.1598921312.282335-21737249"
let carType_host = "https://aip.baidubce.com/rest/2.0/image-classify/v1/
car" + "?access_token=" + "\(access_token)"

if let url = URL(string: carType_host) {
var request = URLRequest(url: url)
request.setValue("application/x-www-form-urlencoded", forHTTPHeaderfield:
"Content-Type")
request.httpMethod = "POST"

let cs = NSCharacterSet(charactersIn: "/=+%").inverted
let image_urlEncode = data_base64_str!.addingPercentEncoding(withA
llowedCharacters: cs)
let postString = "image=\(image_urlEncode!)&top_num=5&baike_num=1"
request.httpBody = postString.data(using: .utf8)
URLSession.shared.dataTask(with: request) { (data, response, error) in
     if error != nil {
         print("error")
     }
     else {
         let rs = String(data: data!, encoding: String.Encoding.utf8) 
         print(rs!)
       }
    }
    .resume()
}

{
    "log_id": 4368540366187197442,
    "location_result":
    {
    "width": 386.4585876464844,
    "top": 81.3405532836914,
    "height": 183.9795532226562,
    "left":58.03330230712891
    },
    "result": 
    [
        { 
        "score": 0.9767324924468994,
        "year":"2014-2017",
        "baike info":
        {
        "baike_url": "/item/%E5%A5%87%E7%91%9EE5/475143",
        "image_url":
             "/pic/5882b2b7d0a20cf47a91d7777c094b36acaf9910",
        "description":
             "2014款奇瑞E5是国内科技家轿的引领者,带领消费者悦享领先科技。"
        },
    "name": "奇瑞E5"
    },
    {
    "score": 0.007103727199137211,
    "name":"奇瑞旗云",
    "year":"2010-2013"
    },
    {
    "score": 0.003686367534101009,
    "name":"奇瑞艾瑞泽 7",
    "year":"2016-2017"
    },
    {
    "score": 0.001757977530360222,
    "name":"奇瑞E3",
    "year":"2015-2017"
    },
    {
    "score":0.001047104829922318,
    "name":"奇瑞A5",
    "year":"2015"
    }
  ],
  "color_result": "黑色"
}
 //
//ViewController.swift
// CameraUsage
//
// Created by Zhifeng Chen on 2020/8/2.
// Copyright • 2020 Zhifeng Chen. All rights reserved.
//

import UIKit


class ViewController: UIViewcontroller , UINavigationControllerDelegate,UITmagePickerControllerDelegate{
    //设置因像显示用的outlet,就是变量 car ImageView
    @IBOutlet weak var carImageView: UIImageView!
    //设置 Action,由相册按钮事件触发
    @IBAction func onLibrary (_sender: UIButton) {
        //设置相册拍照的控制器
        let vc = UIImagePickerController ()
        //设置为相册
        vC. sourceType = .photoLibrary
        vc.allowsEditing = true
        vc.delegate = self
        present (vc, animated: true)
        } 
        //设置Action,由拍照按钮事件触发
        @IBAction func oncamera( sender: UIButton) {
            let vc = UlImagePickerController ()
            //设置为摄像头
            vc. sourceType = .camera
            vc.allowsEditing = true
            vc. delegate = self
            present (vC, animated: true)
        }
            //相册获取图片需要调用的 Delegate
            func imagePickerController|_ picker: UIImagePickerController didFinishPickingMediawithInfo info: [UI ImagePickerController.InfoKey: Any]){
            picker. dismiss (animated: true)
            guard let image = infol.editedImage\ as? UI Image else {
                return
        }
        // 将相册图片显示在 carImageview 中
        carImageView.image = image
    }
}

//
// ViewController.swift
// CameraUsage
// 
// Created by Zhifeng Chen on 2020/8/2.
// Copyright © 2020 Zhifeng Chen. All rights reserved.
//

import UIKit


class viewcontroller: UIViewcontroller , UINavigationcontrol1erDelegate,UIInagePickercontrollerDelegatet{
    //设置图像显示用的outlet,就是变量 car Imageview
    @IBOutlet weak var carImageview : UIImageview!
    //显示识别出来的车辆名称型号
    @IBOutlet weak var carDetails: UILabel !
    //设置 Action,由相册按钮事件触发
    @IBAction func onlibrary ( sender: UIButton) {
        //设置相册拍照的控制器
        let ve = UIImagePickercontroller ()
        //设置为相册
        vC.sourceType = .photoLibrary
        vc.allowsEditing = true
        vc.delegate = self
        present (vc, animated: true)
        }
        // 设置Action,由拍照按钮事件触发
        @IBAction func onCamera ( sender: UIButton) {
            let vc = UIInagePickerController ()
            //设置为摄像头
            vc. sourceType = .camera
            vc.allowsEditing = true
            vc.delegate = self
            present (vc, animated: true)
            }
            //相册获取图片需要调用的 Delegate
            func imagePickerController ( picker: UIImagePickerController,didFinishPickingMediaWithInfo info: [UIImagePickerController. InfoKey : Any]) {
                picker.dismiss (animated: true)
                guard let image = info [.editedImage] as? UIImage else {
                    return
        }
            //将相册图片显示在 carImageview 中
             carImageView.image = image
    //获得百度AI平台access_token
    Let access token = get baidu_ token ()
    if access_token == "" {
        return
    }
    else {
    //从百度AI获得车型信息
    get_car_ type (access token: access_token)
    }
}

//传入有效的access_ token,上传图片,获得车型信息
func get car type (access token: String) {
    //获取显示的图片,,并保存为jpg格式
    let image = carImageView. image
    //let data = UIImagePNGRepresentation (image)
    guard let data = image!. jpegData (compressionQuality: 0.5) else (
        return
    }
    //将图片进行 base64 编码
    let data base64 str = data.base64Encodedstring ()
    //准备好获取车型的AB工 的URI, 的字符串
    let carType host = "https: //aip.baidubce.com/ rest /2.0/ image-classify/v1/car" + "?access token=" + "' (access token) "
    //从字符串转换为 URL
    if let url = URI (string: carrype host) {
        //从 URI 生成 URIRequest
        var reguest = URLReguest (url: url)
        //设置 ETP HEADER 中的 content-Type 为 application/x-www-form-urlencoded
        request. setValue ("application/x-www-form-urlencoded", forHTTPHeaderField:"content-Type")
        //设置为 POST方法
        request.httpMethod = "POST"
        //将图片文件进行 urlencode 转码
        let cs = NSCharacterset (charactersIn: "/=+8").inverted
        let image urlEncode = data base64 str .addingPercentEncoding (withAllovedCharacters:cs)
        //合并三个参数为一个字符串
        let poststring = "image=1 (image_ ur1Encode !) atop num=5abaike num-1"
        //将字符串转为UTF8 类的数据
        request.httpBody = postString.data (using: .utf8)
        //URLSession 调用
        URISession. shared.dataTask (with: request) { (data, response,error) in
        if error != nil {
            print("error")
            }
            else {
                if let json = try? JSONSerialization. jsonObject (with:data!, options: .allowFragments) as? [String : Any] (
                    let result = son ["result") as! Array<Dictionary<String, Any>>
                    let name = result [0] ("name"] as! String
                    var description ="非车类”
                    if name != n 非车类"{
                        let baike info = result [0] ["baike info"] as!Dictionary<String, String>
                        if let details = baike info["description"] {
                            description = details
                    }
                    else {
                    desoription = "百度百科无此车资料"
                }
            }
            //转入主线程
            DispatchQueue.main.async {
                self .carDetails.text = description
                self.carName.text = name
                }
            }
        }
    }
    •resume ( )
    }
}
//以信号量方式等待网络结果返回access_token,如果没有成功,则返回"”
func get baidu_ token () -›String {
    let API_Key = "EIpAlhdD7i5152EsiNgpU0F1"
    let Secret_Key = "p8EZWg4ag]DOxABmKvBYSNyZ1ŸzGFqbm"
    let token host = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client credentials&client id=\(API Key) §client secret=\ (Secret _Key) "

    var access token = ""
    //设置信号量
    let semaphore: DispatchSemaphore = DispatchSemaphore (value: 0)

    if let url = URL (string: token host) {
        URI.Session. shared. datalask (with: url) { (data, response, error) in 
            iferror!= nil {
            print ("network error")
            }
            else {
                if let jnon - try? JSONSerialization.)sondbject (with:data!,options: .allowFragments) as? [String : Any] {
                    access_token - jnon["access_token"] as! string
                //发出信号量
                semaphore.signal()
            }
            .resume()}
            else {
                print("url error")
                // 等待信号量
                semaphore.wait()
                return access_token
            }
        }