程序员随笔:使用来自服务器的图像(有源码)

如果您是移动应用程序开发人员,则在某个时间点您需要与后端进行互动。您可能需要做的其中一项任务是从服务器检索并显示图像,或将图像提交给该服务器。提交图像时应该使用什么格式?如何将从服务调用接收的字节转换为图像?

让我们将整个堆栈从服务器构建到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中。

您现在应该对如何将文本以外的对象发送到服务器有一个基本的了解 - 以及如何检索它们。恭喜!

原文地址:http://blog.51cto.com/13518796/2107758

时间: 2024-10-12 04:09:14

程序员随笔:使用来自服务器的图像(有源码)的相关文章

软考程序员随笔-----4

软件工程基础知识 软件设计是软件工程的核心 理解Gantt图和PERT图 属于进度管理描述进度安排的常见图形 对与DFD图(数据流图) 了解DFD的基本成分 (属于结构化分析方法 ) 数据流 ,加工,数据存储 ,外部实体 .. 软件测试 方法分为: 静态测试和动态测试 . 静态测试分为 人工检测和计算机辅助静态检测 .动态检测分为:白盒测试和黑盒测试 其中白盒测试为(结构测试):测试者完全了解程序的内部结构和处理过程   黑盒测试(功能测试) 测试者完全不考虑程序的内部结构和处理过程,只关注测试

Android程序员,证明你读过安卓源码的最好方式。 原创 kankanStyle

第一个很逗比的类 包名:android.util 类名:Config This class was deprecated in API level 14. This class is not useful, it just returns the same value for all constants, and has always done this. Do not use it. 这个类在API 14被弃用.这个类不是很有用,它只是返回相同的值常量,并一直这样做.^_^不要使用它. 包名:

程序员网址导航

社区.问答 infoQ infoQ通过视频.文章.沙龙等方式促进软件开发领域知识与创新的传播 stackoverflow 高质量的国外IT问答网站,这里汇聚了全球的程序员精英为你回答问题 SegmentFault 中文版的stackoverflow, 专注IT问答社区 Quora Quora 由FB前雇员创办的问答网站 知乎 国内 No.1 的问答社区, 网友讨论气氛浓厚且专业, 苦逼网很多网址在知乎收集, 自扔肥皂感谢- v2ex 如果你上班无聊,想看同行们都在聊些什么,这个适合你. Hack

程序员必读书单

作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文地址:http://www.cnblogs.com/figure9/p/developer-reading-list.html 关于 本文把程序员所需掌握的关键知识总结为三大类19个关键概念,然后给出了掌握每个关键概念所需的入门书籍,必读书籍,以及延伸阅读.旨在成为最好最全面的程序员必读书单. 前言 Reading makes a full man; conference a ready man; and writing

程序员必读书

前言 Reading makes a full man; conference a ready man; and writing an exact man. Francis Bacon 优秀的程序员应该具备两方面能力: 良好的程序设计能力: 掌握常用的数据结构和算法(例如链表,栈,堆,队列,排序和散列): 理解计算机科学的核心概念(例如计算机系统结构.操作系统.编译原理和计算机网络): 熟悉至少两门以上编程语言(例如C++,Java,C#,和Python): 专业的软件开发素养: 具备良好的编程

程序员必读书单(转)

作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://lucida.me/blog/developer-reading-list/ 关于 本文把程序员所需掌握的关键知识总结为三大类19个关键概念,然后给出了掌握每个关键概念所需的入门书籍,必读书籍,以及延伸阅读.旨在成为最好最全面的程序员必读书单. 前言 Reading makes a full man; conference a ready man; and writing an exact man.

程序员必读书目

作者:Lucida 微博:@peng_gong 豆瓣:@figure9 原文链接:http://lucida.me/blog/developer-reading-list/ 关于 本文把程序员所需掌握的关键知识总结为三大类19个关键概念,然后给出了掌握每个关键概念所需的入门书籍,必读书籍,以及延伸阅读.旨在成为最好最全面的程序员必读书单. 前言 Reading makes a full man; conference a ready man; and writing an exact man.

程序员必读书单 1.0

程序员必读书单 1.0 发表于 2015-02-25   |   分类于 阅读  |   暂无评论 转自:http://zh.lucida.me/blog/developer-reading-list/ 本文把程序员所需掌握的关键知识总结为三大类19个关键概念,然后给出了掌握每个关键概念所需的入门书籍,必读书籍,以及延伸阅读.旨在成为最好最全面的程序员必读书单. 前言 Reading makes a full man; conference a ready man; and writing an

什么是真正的程序员

什么是真正的程序员 这篇文章的原文来自:A Little Printf Story作者仿照<小王子>中的情节,通过小printf遇见的不同类型的程序员,最后悟出什么才是真正的程序员!第一次翻译有很多不妥,欢迎留言指正. 文章略长,但是耐心读完,你肯定会受益良多! 第一章 (推荐看完整篇文章,再回过头看一遍第一章) 我非常幸运出生在一个电脑和电子游戏还没有普遍的时代.所以我可以和我的小伙伴们一起玩耍,同时发明属于我们的游戏. 我们十分会玩:用树枝做成'???'.我们可以用树枝做出任何东西,除'回