let package = Package( name: "SwiftImageServer", dependencies: [
.Package(url: "https://github.com/IBM-Swift/Kitura.git", majorVersion: 1)
])
你可以運行一個swift package fetch,你應該看到SwiftPM克隆Kitura和它需要的一切。
旋轉xcodeproj swift package generate-xcodeproj並讓我們編碼!
創建一個Kitura服務器
後端將會非常簡單,所以我們只是在努力main.swift。
首先添加我們需要的所有樣板:
import Kitura
import Foundation
// Create a Router that we can use to create REST endpoints
let router = Router()
// Specify that we want an HTTP server that we can reach with http://localhost:8090
Kitura.addHTTPServer(onPort: 8090, with: router)
// Start the server
Kitura.run()
我喜歡這些日子創造的東西是多麼容易。三行代碼,你有一個服務器運行。這是一個恥辱,它不能做太多。我們來解決這個問題。
從GET端點返回圖像
var latestImage: Data? = nil
// http://localhost:8090/latestImage
router.get("/latestImage") {
request, response, next in
defer { next() }
guard let image = latestImage else {
response.status(.preconditionFailed).send("No image is available")
return
}
response.send(data: image)
}
你以為我們正在發送圖像?
這看起來像一個數據對象,而不是 UIImage?這就是有趣的地方。你永遠不會將圖像作為圖像發送。所有圖像都以簡單易用的格式進行數據打包。當我們向服務器發送圖像和從服務器發送圖像時,我們需要將其打包為數據對象,然後發送。我們將在iOS應用程序中將其表示為UIImage。
注意guard let image = latestImage。
在我們設置latestImage變量之前,這會失敗。讓我們構建接收圖像的端點,以便設置latestImage變量。
將圖像提交給POST端點
接下來,我們將構建將用於提交圖像的端點。
// Create a POST endpoint: http://localhost:8090/image
router.post("/image") {
request, response, next in
defer { next() }
var data = Data()
do {
// Read the body of the request into the data object
try _ = request.read(into: &data)
latestImage = data
response.status(.OK).send("Image received")
} catch(let error) {
response.status(.internalServerError)
.send("Something went wrong when reading the image data")
}
}
我們已經創建了一個端點,該端點需要包含圖像數據的原始主體的POST請求。請記住,服務器只知道數據,而不是UIImage,因此iOS應用程序將不得不將圖像轉換為數據對象。
這是我們的整個服務器完成!
正在運行
需要已完成的服務器,可以關注並私信我
運行可執行目標。這是矩陣式電腦屏幕,而不是黃色的飯盒。
繼續運行,我們將構建iOS應用程序。
客戶端應用程序
關注我並且私信我,提供了iOS應用程序的完整示例代碼。
創建項目
創建一個新的Single View iOS應用程序。我們將需要修改Info.plist。我們需要獲得訪問照片庫的權限才能選擇圖片。我們還需要修改App Transport安全設置以發出HTTP網絡請求,而不是HTTPS(我們的本地Kitura服務器為HTTP)。
將以下內容添加到項目中Info.plist:
我們將添加一個按鈕,允許我們從照片庫中選擇一幅圖像,並將其提交給我們之前構建的服務器。
我們將通過在視圖控制器中添加一個按鈕來開始Main.storyboard:
現在,將其掛接ViewController.swift並添加代碼以將其發佈到我們的後端。
讓我們將IBAction連接到"Pick Image"按鈕,我們使用UIImagePickerController來選擇圖像。
@IBAction func pickImage(_ sender: Any) {
guard UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else { return }
let imagePickerController = UIImagePickerController()
imagePickerController.sourceType = .photoLibrary
imagePickerController.delegate = self
present(imagePickerController, animated: true, completion: nil)
}
我們將ViewController設置為UIImagePickerController的委託。添加一個符合委託協議的擴展,該協議也處理任何拾取的圖像。設置委託也需要符合UINavigationControllerDelegate,所以也要添加它。
extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
public func imagePickerController(
_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [String: Any]) {
if let image = info[UIImagePickerControllerOriginalImage]
as? UIImage {
submit(image: image)
} else if let image = info[UIImagePickerControllerEditedImage as? UIImage {
submit(image: image)
}
picker.dismiss(animated: true)
}
}
我們可以選擇一張圖片,我們隨時可以處理它。注意submit(image:)上面例子中的函數。我們現在將創建該功能,並將圖像提交給我們的服務器。
func submit(image: UIImage) {
let session = URLSession(
configuration: URLSessionConfiguration.default)
guard let url = URL(string: "http://localhost:8090/image") else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.httpBody = UIImagePNGRepresentation(image)
let dataTask = session.dataTask(with: request) {
(data, response, error) in
if let error = error {
print("Something went wrong: \(error)")
}
if let response = response {
print("Response: \n \(response)")
}
}
dataTask.resume()
}
從服務器接收圖像
現在我們可以將圖像作為數據對象提交,我們需要構建用於接收圖像作為數據並將其轉換為普通舊UIImage的功能。
首先在Main.storyboard中添加一個圖像視圖和另一個按鈕到視圖控制器:
當用戶點擊新按鈕時,我們將調用latestImage端點來檢索作為數據對象發送到服務器的最後一個圖像。然後我們將它轉換為UIImage並將其顯示在圖像視圖中。
@IBOutlet weak var imageView: UIImageView!
@IBAction func showLatestImage(_ sender: Any) {
let session = URLSession(
configuration: URLSessionConfiguration.default)
guard let url = URL(
string: "http://localhost:8090/latestImage") else {
return
}
var request = URLRequest(url: url)
request.httpMethod = "GET"
session.dataTask(with: request) { (data, response, error) in
if let error = error {
print("Something went wrong: \(error)")
}
if let imageData = data {
DispatchQueue.main.async {
self.imageView.image = UIImage(data: imageData)
}
}
}.resume()
}
成品
這是我們的應用程序已經提交了一個圖像到服務器,並從服務器拉出一個圖像來顯示。
當你點擊Pick Image時,你會看到一個UIIImagePickerController,它允許你從照片庫中選擇一個圖像,並在將其轉換為數據對象後將其提交給我們的後端。"顯示最新圖像"按鈕向我們的服務器發出GET請求,以檢索最後發送的圖像,將其轉換為UIImage,然後將其顯示在我們的UIImageView中。
您現在應該對如何將文本以外的對象發送到服務器有一個基本的瞭解 - 以及如何檢索它們。恭喜!
閱讀更多 浪小九 的文章