Alamofire 上传图片入门教程(上)

2024-03-02 07:59

本文主要是介绍Alamofire 上传图片入门教程(上),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Get the lowdown on Alamofire!

提示:
本教程基于 Xcode 7.3, iOS 9.3, 和 Swift 2.2

Alamofire 是一个为 iOS 和 Mac OS,基于 Swift 的 HTTP 网络库。它在 Apple 的基础网络库上提供了一个优雅的接口,简化了许多常见的网络任务。

Alamofire 提供链式地请求与响应方法,JSON 参数以及响应的序列化和授权,等等。在本教程中,你将使用 Alamofire 来完成基本的网络任务,包括上传文件以及使用第三方库 RESTful API 来请求数据。

注:关于 RESTful API 可以参考这篇博客 RESTful API

Alamofire 的优雅是一个事实,它完全由 Swift 编写,没有任何 Objective-C 的代码,也不是继承自 AFNetworking。

你需要理解一些 HTTP 的基本概念,以及了解苹果的网络类,比如 NSURLSessionNSURLConnection

虽然 Alamofire 掩盖了一些实现细节,但是如果你需要解决你的网络请求,有一些背景知识也是不错的。你也需要使用 CocoaPods 把 Alamofire 安装到你的教程工程中。

入门

下载 初始工程。下载完成后,打开工程运行,会发现中间有一个按钮可以选择图片,点击按钮会访问系统的相册,随便选择一张图片,背景就会被这张图片代替。但是现在的工程是一个初始工程,好多功能没有完成,如下图:

PhotoTagger-start.png

最终完成的效果图会是下面的样子:

PhotoTaggerDemo.gif

Imagga API

Imagga 是一个把图像识别作为服务的平台,为开发者和企业提供了可扩展的图像标注 API,以及图像密集的云应用。你可以从 他们的自动标注服务 下载一个示例程序。

你需要在 Imagga 网站创建一个免费的开发者账户,才能完成这次教程。Imagga 在每次进行 HTTP 请求的时候都需要一个授权头,所以必须注册才能使用他们的服务。去 https://imagga.com/auth/signup/hacker 完成注册吧。注册成功后你会看到类似下面的界面:

Imagga-Dashboard.png

Authorization 选项是一个 token,后面你会用到。

注意:
确保你拷贝了整个 token,因为这个 token 很长。

你将会使用 Imagga 作为上传图片的服务器,给图片标注和设置颜色。你可以在 http://docs.imagga.com 了解到所有的 API。

安装依赖包

在工程主目录创建一个名为 Podfile 的文件,并打开这个文件,可以使用下面的方式:

touch Podfile
open Podfile

然后输入下面的内容:

platform :ios, '9.0'inhibit_all_warnings!
use_frameworks!target 'PhotoTagger' dopod 'Alamofire', '~> 3.1.2'
end

接下来,如果你的电脑上没有安装 CocoaPods,点击下面链接进行安装 最新版 CocoaPods 的安装流程。

关闭刚才打开的工程,打开终端进入工程目录。输入 pod install,稍等片刻,完成后会生成一个名为 PhotoTagger.xcworkspace 的文件。然后编译运行你的工程,你会发现没有任何改变,这就对了,下一步从 RESTful 服务器添加一些 HTTP 请求,会返回 JSON 数据。

Alamofire 的好处是什么?

苹果已经提供了 NSURLSession 和其他的类来下载内容,那为什么还要用 Alamofire 呢?因为 Alamofire 基于 NSURLSession,并且它可以让你编写的代码的时候更容易。你不用话费太大的精力就可以获取互联网上的数据,而且你的代码还会很简洁易读。

下面是 Alamofire 中几个主要的函数:

.upload:以分解成部分的形式,数据流的形式,整个文件的形式或者数据的形式上传文件。
.download:下载文件或者暂停后继续下载。
.request:每一个 HTTP 请求和文件传输都不相关。

这些 Alamofire 函数的范围是一个 module,而不是类或结构体。Alamofire 的底层都是类和结构体,比如有 ManagerRequest, 和Response,但是你一开始用的时候不必全都理解 Alamofire 其他的结构体。下面是一个例子:
下面直接使用的 NSURLSession

// With NSURLSession
public func fetchAllRooms(completion: ([RemoteRoom]?) -> Void) {let url = NSURL(string: "http://localhost:5984/rooms/_all_docs?include_docs=true")!let urlRequest = NSMutableURLRequest(URL: url,cachePolicy: .ReloadIgnoringLocalAndRemoteCacheData,timeoutInterval: 10.0 * 1000)urlRequest.HTTPMethod = "GET"urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")let task = urlSession.dataTaskWithRequest(urlRequest){ (data, response, error) -> Void inguard error == nil else {print("Error while fetching remote rooms: \(error)")completion(nil)return}guard let json = try? NSJSONSerialization.JSONObjectWithData(data!,options: []) as? [String: AnyObject] else {print("Nil data received from fetchAllRooms service")completion(nil)return}guard let rows = json["rows"] as? [[String: AnyObject]] {print("Malformed data received from fetchAllRooms service")completion(nil)return}var rooms = [RemoteRoom]()for roomDict in rows {rooms.append(RemoteRoom(jsonData: roomDict))}completion(rooms)}task.resume()
}

下面是使用 Alamofire 的方式:

// With Alamofire
func fetchAllRooms(completion: ([RemoteRoom]?) -> Void) {Alamofire.request(.GET,"http://localhost:5984/rooms/_all_docs",parameters: ["include_docs": "true"],encoding: .URL).validate().responseJSON { (response) -> Void inguard response.result.isSuccess else {print("Error while fetching remote rooms: \(response.result.error)")completion(nil)return}guard let value = response.result.value as? [String: AnyObject],rows = value["rows"] as? [[String: AnyObject]] else {print("Malformed data received from fetchAllRooms service")completion(nil)return}var rooms = [RemoteRoom]()for roomDict in rows {rooms.append(RemoteRoom(jsonData: roomDict))}completion(rooms)}
}

上传文件

打开 ViewController.swift,把下面的代码加到类的底部:

// Networking calls
extension ViewController {func uploadImage(image: UIImage, progress: (percent: Float) -> Void,completion: (tags: [String], colors: [PhotoColor]) -> Void) {guard let imageData = UIImageJPEGRepresentation(image, 0.5) else {print("Could not get JPEG representation of UIImage")return}}
}

上面的代码的作用是上传图片到 Imagga。

接下来,在 imagePickerController(_:didFinishPickingMediaWithInfo:) 方法里,在 imageView.image = image 后面加入下面的代码:

// 1
takePictureButton.hidden = true
progressView.progress = 0.0
progressView.hidden = false
activityIndicatorView.startAnimating()uploadImage(image,progress: { [unowned self] percent in// 2self.progressView.setProgress(percent, animated: true)},completion: { [unowned self] tags, colors in// 3self.takePictureButton.hidden = falseself.progressView.hidden = trueself.activityIndicatorView.stopAnimating()self.tags = tagsself.colors = colors// 4self.performSegueWithIdentifier("ShowResults", sender: self)
})

在 Alamofire 中所有对象都是异步的,也就意味着你会以异步的方式更新 UI:

  1. 隐藏上传按钮,同时显示显示进度条。
  2. 当文件上传的时候,progress 闭包会以百分比的形式进行更新,改变的多少同步显示在进度条上。
  3. 当上传文件完成时,completion 闭包才会执行,设置控件的状态变为原始状态。
  4. 最后,Storyboard 会将成功的(或者不成功)上茶传结果显示到屏幕上,接口并不会基于错误发生改变。

接下来,在 ViewController.swift 中添加下面的代码:

import Alamofire

上面的代可以会让你使用 Alamofire 模块提供的代码。

下面,返回到 uploadImage(_:progress:completion:) 并且在guard 判断后面添加下面的代码:

Alamofire.upload(.POST,"http://api.imagga.com/v1/content",headers: ["Authorization" : "Basic xxx"],multipartFormData: { multipartFormData inmultipartFormData.appendBodyPart(data: imageData, name: "imagefile",fileName: "image.jpg", mimeType: "image/jpeg")},encodingCompletion: { encodingResult in}
)

确保替换『Basic xxx』用你自己在 Imagga 网站生成的 token。

接下来,在 encodingCompletion闭包里添加下面的代码:

switch encodingResult {
case .Success(let upload, _, _):upload.progress { bytesWritten, totalBytesWritten, totalBytesExpectedToWrite indispatch_async(dispatch_get_main_queue()) {let percent = (Float(totalBytesWritten) / Float(totalBytesExpectedToWrite))progress(percent: percent)}}upload.validate()upload.responseJSON { response in}
case .Failure(let encodingError):print(encodingError)
}

这段代码调用 Alamofire 上传功能,通过在计算来更新进度条。

注意:
Alamofire 并不会保证调用过程会在主队列上回调;因此你必须通过向主队列调度来更新用户界面。有一些 Alamofire 的回调,比如 responseJSON,都会默认在主队列调用。例如:

dispatch_async(queue ?? dispatch_get_main_queue()) {let response = ...completionHandler(response)
}

为了改变默认的做法,你需要给 Alamofire 提供一个 dispatch_queue_t

添加下面的代码到 upload.responseJSON

// 1.
guard response.result.isSuccess else {print("Error while uploading file: \(response.result.error)")completion(tags: [String](), colors: [PhotoColor]())return
}
// 2.
guard let responseJSON = response.result.value as? [String: AnyObject],uploadedFiles = responseJSON["uploaded"] as? [AnyObject],firstFile = uploadedFiles.first as? [String: AnyObject],firstFileID = firstFile["id"] as? String else {
    print("Invalid information received from service")
    completion(tags: [String](), colors: [PhotoColor]())
    return
}
print("Content uploaded with ID: \(firstFileID)")
// 3.
completion(tags: [String](), colors: [PhotoColor]())

下面是每步的解释:
1. 检查响应是否成功;如果不成功,输出错误信息并调用 completion
2. 检查响应的每个部分,验证所期望的类型是收到的实际类型,如果 firstFileID 没有被解析,那么输出错误信息,并调用completion
3. 调用 completion 来更新 UI。你没有任何下载的标志或颜色,所以简化调用数据为空的情况。

注意:
每一个响应都有一个结果,包括枚举值和类型。使用自动验证,当它返回一个合法的 HTTP 码(在200-299之间的内容类型都被认为是可以接受的)。
你可以通过添加 .validate 手动执行验证,代码如下:

Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"]).validate(statusCode: 200..<300).validate(contentType: ["application/json"]).response { response in// response handling code
}

如果你在上传期间发生错误,UI 并不会显示错误;它仅仅会返回没有标志或颜色给用户。这不是良好的用户体验,但是在本次教程中确实有上面所说的。

编译运行工程代码,选择一个 image 然后会看到进度条发生了变化,上传完成后,你会看到下面的信息:

ImaggaUploadConsole.png

你已经成功的上传图片!

sad-forever-alone-happy.jpg

下篇地址

原帖地址

这篇关于Alamofire 上传图片入门教程(上)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/765436

相关文章

C#实现将Excel表格转换为图片(JPG/ PNG)

《C#实现将Excel表格转换为图片(JPG/PNG)》Excel表格可能会因为不同设备或字体缺失等问题,导致格式错乱或数据显示异常,转换为图片后,能确保数据的排版等保持一致,下面我们看看如何使用C... 目录通过C# 转换Excel工作表到图片通过C# 转换指定单元格区域到图片知识扩展C# 将 Excel

JS+HTML实现在线图片水印添加工具

《JS+HTML实现在线图片水印添加工具》在社交媒体和内容创作日益频繁的今天,如何保护原创内容、展示品牌身份成了一个不得不面对的问题,本文将实现一个完全基于HTML+CSS构建的现代化图片水印在线工具... 目录概述功能亮点使用方法技术解析延伸思考运行效果项目源码下载总结概述在社交媒体和内容创作日益频繁的

使用Node.js制作图片上传服务的详细教程

《使用Node.js制作图片上传服务的详细教程》在现代Web应用开发中,图片上传是一项常见且重要的功能,借助Node.js强大的生态系统,我们可以轻松搭建高效的图片上传服务,本文将深入探讨如何使用No... 目录准备工作搭建 Express 服务器配置 multer 进行图片上传处理图片上传请求完整代码示例

基于Python实现高效PPT转图片工具

《基于Python实现高效PPT转图片工具》在日常工作中,PPT是我们常用的演示工具,但有时候我们需要将PPT的内容提取为图片格式以便于展示或保存,所以本文将用Python实现PPT转PNG工具,希望... 目录1. 概述2. 功能使用2.1 安装依赖2.2 使用步骤2.3 代码实现2.4 GUI界面3.效

Python实现AVIF图片与其他图片格式间的批量转换

《Python实现AVIF图片与其他图片格式间的批量转换》这篇文章主要为大家详细介绍了如何使用Pillow库实现AVIF与其他格式的相互转换,即将AVIF转换为常见的格式,比如JPG或PNG,需要的小... 目录环境配置1.将单个 AVIF 图片转换为 JPG 和 PNG2.批量转换目录下所有 AVIF 图

详解如何通过Python批量转换图片为PDF

《详解如何通过Python批量转换图片为PDF》:本文主要介绍如何基于Python+Tkinter开发的图片批量转PDF工具,可以支持批量添加图片,拖拽等操作,感兴趣的小伙伴可以参考一下... 目录1. 概述2. 功能亮点2.1 主要功能2.2 界面设计3. 使用指南3.1 运行环境3.2 使用步骤4. 核

Java图片压缩三种高效压缩方案详细解析

《Java图片压缩三种高效压缩方案详细解析》图片压缩通常涉及减少图片的尺寸缩放、调整图片的质量(针对JPEG、PNG等)、使用特定的算法来减少图片的数据量等,:本文主要介绍Java图片压缩三种高效... 目录一、基于OpenCV的智能尺寸压缩技术亮点:适用场景:二、JPEG质量参数压缩关键技术:压缩效果对比

使用Python开发一个简单的本地图片服务器

《使用Python开发一个简单的本地图片服务器》本文介绍了如何结合wxPython构建的图形用户界面GUI和Python内建的Web服务器功能,在本地网络中搭建一个私人的,即开即用的网页相册,文中的示... 目录项目目标核心技术栈代码深度解析完整代码工作流程主要功能与优势潜在改进与思考运行结果总结你是否曾经

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

使用C#代码在PDF文档中添加、删除和替换图片

《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当