序言:
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]? {
let result = selectAllDatabaseSQL(tableName: tableName)
var resultArray = [Dictionary]()
var dic = [String:String]()
result.mysqlResult?.forEachRow(callback: { (row) in
dic["uuid"] = row[1]
resultArray.append(dic)
})
return resultArray
}
}