Swift + Perfect開發(fā)你的服務(wù)器(高級(jí)版)

序言:

1.以下代碼中的意義,會(huì)在代碼里解釋,用比較容易理解的詞語(yǔ)注釋,若有晦澀之處,可私信于我。
2.現(xiàn)已假設(shè)讀者閱讀過(guò)我的另外兩篇文章??
Swift Perfect開發(fā)你的服務(wù)器(初級(jí)版)
Swift Perfect開發(fā)你的服務(wù)器(中級(jí)版)
3.準(zhǔn)備Peffect助手工具:Perfect Assistant 3.0創(chuàng)建服務(wù)器項(xiàng)目

基于“以上”編譯成功后,在默認(rèn)的main.swift文件里,全部清空,然后替換成我的代碼:

// 導(dǎo)入所需要的庫(kù)
import PerfectLib
import PerfectHTTP
import PerfectHTTPServer
import PerfectMustache

import Foundation

let root = "./webroot"

// 配置服務(wù)器端口、根目錄等
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() // 開啟服務(wù)器
} catch PerfectError.networkError(let err, let msg) {
    print("Netword error thrown: \(err) \(msg)")
}

打開項(xiàng)目,新建RoutesManager.swift,添加以下代碼

import Foundation
import PerfectLib
import PerfectHTTP
import PerfectHTTPServer

// 路由
class BasicRoutes {
    
    var routes: [Route] {
        return [
    /*
     1.這里定義接口,為客戶端服務(wù),我們請(qǐng)求的方法,和url,在這里設(shè)置。
     2.由于我們還沒(méi)有新建TestUpload方法,所以這里暫時(shí)會(huì)報(bào)錯(cuò),先不管,往下看,go go go
     */
            Route(method: .post, uri: "/api/testUploadImage", handler: TestUpload) 
        ]
    }

}

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

import Foundation
import PerfectLib
import PerfectHTTP

let testStr = "CRTest"
/* 
 圖片上傳方法:
1. request是客戶端的請(qǐng)求,有些參數(shù)我們可在這里獲取
2.response是我們給客戶端的響應(yīng),想要返回的數(shù)據(jù),在這設(shè)置
*/
func TestUpload(request: HTTPRequest, response: HTTPResponse) {
    
    do{
        
        guard let uploads = request.postFileUploads, uploads.count >= 1 else {
            let successArray: [String:Any] = ["result":"false", "msg":"請(qǐng)選擇正確的圖片數(shù)量"]
            let jsonStr = try successArray.jsonEncodedString()
            try response.setBody(json: jsonStr)
            response.completed()
            return
        }
/* 
這里的iOSTime參數(shù)是我在客戶端那邊傳過(guò)來(lái)的當(dāng)前本地時(shí)間。
其實(shí)是可以在這設(shè)置的,但由于客戶端和服務(wù)器的精確時(shí)間并不一致,
所以采用了客戶端的時(shí)間為標(biāo)準(zhǔn),同時(shí)也鍛煉了我們傳參的能力
*/
        guard let currentTime = request.param(name: "iOSTime") else {
            return
        }
        #if os(Linux)
// Dir.workingDir.parentDir拿到父目錄,也可在本地運(yùn)行打印看看是什么東東
        guard let parentPath = Dir.workingDir.parentDir?.path else {
            return
        }
        
// 設(shè)置我們存放圖片的路徑,同時(shí)nginx的配置也要與這個(gè)路徑有關(guān)聯(lián),看過(guò)我之前的文章會(huì)不陌生!
        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

        // 官網(wǎng)上摘取的代碼
        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環(huán)境運(yùn)行)
                        let resultPath = fileDir.path + upload.fileName
                        // Ubuntu存放到數(shù)據(jù)庫(kù)的路徑
                        let realPath = "http://www.crios.cn/pictures/" + "\(currentTime)" + upload.fileName
                        let _ = try thisFile.moveTo(path: resultPath, overWrite: true)
                        
                        // 這里會(huì)報(bào)錯(cuò),DataBaseManager.swift還沒(méi)有創(chuàng)建,先不管,會(huì)在下一步執(zhí)行
                        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 {
// 通用的返回?cái)?shù)據(jù),可參照我的代碼或官網(wǎng)的、設(shè)定
                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": "后臺(tái)格式錯(cuò)誤", "msg": "成功"]
                let jsonStr = try successArray.jsonEncodedString()
                try response.setBody(json: jsonStr)
                response.completed()
            }
            
        }
        
    }catch{
        Log.error(message: "\(error)")
    }
}

新建MySQL數(shù)據(jù)庫(kù)管理類

import Foundation
import PerfectMySQL

// MARK: 數(shù)據(jù)庫(kù)信息
#if os(Linux) // 在Ubuntu下
let user = "root"
let password = "你的密碼"
let dataBase = "test1" // test1數(shù)據(jù)庫(kù)是自己在Navicat Premium圖形工具里創(chuàng)建的
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()                           //創(chuàng)建MySQL對(duì)象
        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: 執(zhí)行SQL語(yǔ)句
    /// 執(zhí)行SQL語(yǔ)句
    ///
    /// - Parameter sql: sql語(yǔ)句
    /// - Returns: 返回元組(success:是否成功 result:結(jié)果)
    @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語(yǔ)句
        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執(zhí)行成功
        
    }
    
    /// 創(chuàng)建表 (查詢是否有此表,若否,則創(chuàng)建)
    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: 鍵值對(duì)( 鍵='值', 鍵='值', 鍵='值' )
    ///   - 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: 鍵值對(duì)
    func selectAllDataBaseSQLwhere(tableName: String, keyValue: String) -> (success: Bool, mysqlResult: MySQL.Results?, errorMsg: String) {
        
        let SQL = "SELECT * FROM \(tableName) WHERE \(keyValue)"
        return mysqlStatement(SQL)
        
    }
    
    // 獲取數(shù)據(jù)庫(kù)某個(gè)表中的所有數(shù)據(jù)
    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項(xiàng)目

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容