阅读 85

Swift + Perfect开发你的服务器(高级版)

###序言: 1.以下代码中的意义,会在代码里解释,用比较容易理解的词语注释,若有晦涩之处,可私信于我。 2.现已假设读者阅读过我的另外两篇文章👇 Swift Perfect开发你的服务器(初级版) Swift Perfect开发你的服务器(中级版) 3.准备Peffect助手工具:Perfect Assistant 3.0创建服务器项目

基于“以上”编译成功后,在默认的main.swift文件里,全部清空,然后替换成我的代码:

// 导入所需要的库
import PerfectLib
import PerfectHTTP
import PerfectHTTPServer
import PerfectMustache

import Foundation

let root = "./webroot"

// 配置服务器端口、根目录等
let server = HTTPServer()
server.serverPort = 8181
server.documentRoot = root

// 配置路由,BasicRoutes在RoutesManager.swift的代码里,往下看,go go go
let basic = BasicRoutes()
server.addRoutes(Routes(basic.routes))

/* 另一种方法
 * var routes = Routes()
 * routes.add(method: .post, uri: "/testUpload", handler: TestUpload)
 * server.addRoutes(routes)
 */
do {
    try server.start() // 开启服务器
} catch PerfectError.networkError(let err, let msg) {
    print("Netword error thrown: \(err) \(msg)")
}

复制代码

打开项目,新建RoutesManager.swift,添加以下代码

import Foundation
import PerfectLib
import PerfectHTTP
import PerfectHTTPServer

// 路由
class BasicRoutes {
    
    var routes: [Route] {
        return [
    /*
     1.这里定义接口,为客户端服务,我们请求的方法,和url,在这里设置。
     2.由于我们还没有新建TestUpload方法,所以这里暂时会报错,先不管,往下看,go go go
     */
            Route(method: .post, uri: "/api/testUploadImage", handler: TestUpload) 
        ]
    }

}
复制代码

新建路由助手类RoutesHelper.swift,然后添加下面代码

import Foundation
import PerfectLib
import PerfectHTTP

let testStr = "CRTest"
/* 
 图片上传方法:
1. request是客户端的请求,有些参数我们可在这里获取
2.response是我们给客户端的响应,想要返回的数据,在这设置
*/
func TestUpload(request: HTTPRequest, response: HTTPResponse) {
    
    do{
        
        guard let uploads = request.postFileUploads, uploads.count >= 1 else {
            let successArray: [String:Any] = ["result":"false", "msg":"请选择正确的图片数量"]
            let jsonStr = try successArray.jsonEncodedString()
            try response.setBody(json: jsonStr)
            response.completed()
            return
        }
/* 
这里的iOSTime参数是我在客户端那边传过来的当前本地时间。
其实是可以在这设置的,但由于客户端和服务器的精确时间并不一致,
所以采用了客户端的时间为标准,同时也锻炼了我们传参的能力
*/
        guard let currentTime = request.param(name: "iOSTime") else {
            return
        }
        #if os(Linux)
// Dir.workingDir.parentDir拿到父目录,也可在本地运行打印看看是什么东东
        guard let parentPath = Dir.workingDir.parentDir?.path else {
            return
        }
        
// 设置我们存放图片的路径,同时nginx的配置也要与这个路径有关联,看过我之前的文章会不陌生!
        let fileDir = Dir(parentPath + "usr/local/sources/pictures/" + currentTime)
        do {
            try fileDir.create()
        } catch {
            Log.error(message: "\(error)")
        }
        #else
        let fileDir = Dir(Dir.workingDir.path + "webroot/pictures")
        do {
            try fileDir.create()
        } catch {
            Log.error(message: "\(error)")
        }
        #endif

        // 官网上摘取的代码
        if let uploads = request.postFileUploads, uploads.count > 0 {
            var ary = [[String:Any]]()
            var pathArr = [String]()
            for upload in uploads {
                ary.append([
                    "fieldName": upload.fieldName,
                    "contentType": upload.contentType,
                    "fileName": upload.fileName,
                    "fileSize": upload.fileSize,
                    "tmpFileName": upload.tmpFileName
                    ])
                // move file to webroot
                let thisFile = File(upload.tmpFileName)
                if (thisFile.path != "") {
                    do {
                        // 本地存放路径(本地即为Mac环境运行)
                        let resultPath = fileDir.path + upload.fileName
                        // Ubuntu存放到数据库的路径
                        let realPath = "http://www.crios.cn/pictures/" + "\(currentTime)" + upload.fileName
                        let _ = try thisFile.moveTo(path: resultPath, overWrite: true)
                        
                        // 这里会报错,DataBaseManager.swift还没有创建,先不管,会在下一步执行
                        let sql = DataBaseManager().createTable(tableName: testStr + currentTime)
                        if sql.success {
                            #if os(Linux)
                            let _ = DataBaseManager().insertDatabaseSQL(tableName: testStr + currentTime, key: "path,currentTime", value: "'\(realPath)','\(currentTime)'")
                            #else
                            let _ = DataBaseManager().insertDatabaseSQL(tableName: testStr + currentTime, key: "path,currentTime", value: "'\(resultPath)','\(currentTime)'")
                            #endif
                        }
                        #if os(Linux)
                        pathArr.append(realPath)
                        #else
                        pathArr.append(resultPath)
                        #endif
                        
                    } catch {

                        let successArray: [String:Any] = ["success": 1, "result": "\(error)", "msg": "失败"]
                        Log.error(message: "\(error)")
                        let jsonStr = try successArray.jsonEncodedString()
                        try response.setBody(json: jsonStr)
                        response.completed()
                    }
                }
            }
            do {
// 通用的返回数据,可参照我的代码或官网的、设定
                let successArray: [String:Any] = ["success": 1, "result": pathArr, "msg": "成功"]
                let jsonStr = try successArray.jsonEncodedString()
                try response.setBody(json: jsonStr)
                response.completed()
            } catch {
                
                let successArray: [String:Any] = ["success": 1, "result": "后台格式错误", "msg": "成功"]
                let jsonStr = try successArray.jsonEncodedString()
                try response.setBody(json: jsonStr)
                response.completed()
            }
            
        }
        
    }catch{
        Log.error(message: "\(error)")
    }
}
复制代码

新建MySQL数据库管理类

import Foundation
import PerfectMySQL

// MARK: 数据库信息
#if os(Linux) // 在Ubuntu下
let user = "root"
let password = "你的密码"
let dataBase = "test1" // test1数据库是自己在Navicat Premium图形工具里创建的
let host = "0.0.0.0"
    
#else
let user = "root"
let password = "你的密码"
let dataBase = "CRTest"
let host = "0.0.0.0"
#endif



open class DataBaseManager {
    
    fileprivate var mysql: MySQL
    internal init() {
        mysql = MySQL.init()                           //创建MySQL对象
        guard connectedDataBase() else {               //开启MySQL连接
            return
        }
    }
    
    // MARK: 开启连接
    private func connectedDataBase() -> Bool {
        
        let connected = mysql.connect(host: host, user: user, password: password, db: dataBase)
        guard connected else {
            print(mysql.errorMessage())
            return false
        }
        print("MySQL Connect Success")
        return true
        
    }
    
    // MARK: 执行SQL语句
    /// 执行SQL语句
    ///
    /// - Parameter sql: sql语句
    /// - Returns: 返回元组(success:是否成功 result:结果)
    @discardableResult
    func mysqlStatement(_ sql: String) -> (success: Bool, mysqlResult: MySQL.Results?, errorMsg: String) {
        
        guard mysql.selectDatabase(named: dataBase) else {            //指定database
            let msg = "NO\(dataBase)Database"
            print(msg)
            return (false, nil, msg)
        }
        
        let successQuery = mysql.query(statement: sql)                      //sql语句
        guard successQuery else {
            let msg = "SQL_Error: \(sql)"
            print(msg)
            return (false, nil, msg)
        }
        let msg = "SQL_Success: \(sql)"
        print(msg)
        return (true, mysql.storeResults(), msg)                            //sql执行成功
        
    }
    
    /// 创建表 (查询是否有此表,若否,则创建)
    func createTable(tableName: String) -> (success: Bool, mysqlResult: MySQL.Results?, errorMsg: String){
        let insert = "SELECT * FROM \(tableName)"
        let statement = mysqlStatement(insert)
        if !statement.success {
            let SQL = "CREATE TABLE \(tableName) (id INT(10) PRIMARY KEY AUTO_INCREMENT, path VARCHAR(255), companyName VARCHAR(255),phoneNumber VARCHAR(255))"
            return mysqlStatement(SQL)
        }
        return mysqlStatement(insert)
    }
//    CREATE TABLE samples (id INT PRIMARY KEY AUTO_INCREMENT, created_at DATETIME, location POINT, reading JSON)
    /// 增
    ///
    /// - Parameters:
    ///   - tableName: 表
    ///   - key: 键  (键,键,键)
    ///   - value: 值  ('值', '值', '值')
    func insertDatabaseSQL(tableName: String, key: String, value: String) -> (success: Bool, mysqlResult: MySQL.Results?, errorMsg: String){
        let SQL = "INSERT INTO \(tableName) (\(key)) VALUES (\(value))"
        return mysqlStatement(SQL)
    }
    
    /// 删
    ///
    /// - Parameters:
    ///   - tableName: 表
    ///   - key: 键
    ///   - value: 值
    func deleteDatabaseSQL(tableName: String, key: String, value: String) -> (success: Bool, mysqlResult: MySQL.Results?, errorMsg: String) {
        
        let SQL = "DELETE FROM \(tableName) WHERE \(key) = '\(value)'"
        return mysqlStatement(SQL)
        
    }
    
    /// 改
    ///
    /// - Parameters:
    ///   - tableName: 表
    ///   - keyValue: 键值对( 键='值', 键='值', 键='值' )
    ///   - whereKey: 查找key
    ///   - whereValue: 查找value
    func updateDatabaseSQL(tableName: String, keyValue: String, whereKey: String, whereValue: String) -> (success: Bool, mysqlResult: MySQL.Results?, errorMsg: String) {
        
        let SQL = "UPDATE \(tableName) SET \(keyValue) WHERE \(whereKey) = '\(whereValue)'"
        return mysqlStatement(SQL)
        
    }
    
    /// 查所有
    ///
    /// - Parameters:
    ///   - tableName: 表
    ///   - key: 键
    func selectAllDatabaseSQL(tableName: String) -> (success: Bool, mysqlResult: MySQL.Results?, errorMsg: String) {
        
        let SQL = "SELECT * FROM \(tableName)"
        return mysqlStatement(SQL)
        
    }
    
    /// 查
    ///
    /// - Parameters:
    ///   - tableName: 表
    ///   - keyValue: 键值对
    func selectAllDataBaseSQLwhere(tableName: String, keyValue: String) -> (success: Bool, mysqlResult: MySQL.Results?, errorMsg: String) {
        
        let SQL = "SELECT * FROM \(tableName) WHERE \(keyValue)"
        return mysqlStatement(SQL)
        
    }
    
    // 获取数据库某个表中的所有数据
    func mysqlGetUserDataResult(tableName: String) -> [Dictionary<String, String>]? {
        
        let result = selectAllDatabaseSQL(tableName: tableName)
        var resultArray = [Dictionary<String, String>]()
        var dic = [String:String]()
        result.mysqlResult?.forEachRow(callback: { (row) in
            dic["uuid"] = row[1]
            resultArray.append(dic)
        })
        
        return resultArray
        
    }
}

复制代码

###代码可从我的Github上下载,并新建了客户端的代码 Perfect项目