程序员随笔:使用来自服务器的图像(有源码)
如果您是移動應用程序開發人員,則在某個時間點您需要與后端進行互動。您可能需要做的其中一項任務是從服務器檢索并顯示圖像,或將圖像提交給該服務器。提交圖像時應該使用什么格式?如何將從服務調用接收的字節轉換為圖像?
讓我們將整個堆棧從服務器構建到iOS應用程序,以了解如何實現。
設置后端
我們將首先構建一個提供RESTful API?的Kitura服務器來完成兩件事:
從客戶端接收圖像
向客戶提供最新的圖像
創建服務器項目
創建一個目錄,并初始化一個新的可執行Swift包。
mkdir mkdir SwiftImageServer && cd SwiftImageServerswift package init --type executable
編輯您的Package.swift文件以指定您需要Kitura軟件包。
import PackageDescription
?
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中。
您現在應該對如何將文本以外的對象發送到服務器有一個基本的了解 - 以及如何檢索它們。恭喜!
轉載于:https://blog.51cto.com/13518796/2107758
總結
以上是生活随笔為你收集整理的程序员随笔:使用来自服务器的图像(有源码)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 搭建Mysql-proxy实现主从同步读
- 下一篇: Openlayers4中实现动态线效果