由于之前一直在忙项目,很久没有写过一篇像样的文章了,现在手上的项目基本是完成了,正好工作时间偷个懒写两篇文章。

将相机或相册图片上传到服务器

先看看最常见的图片上传,也可以选择跳过,后面有直接的封装方法

在实际开发中,图片上传是很常见的功能,比如和朋友圈一样发布一条动态要添加几张图片,或者上传用户头像什么的,这里就介绍如何通过第三方库Alamofire进行图片上传(这里使用的是Swift,下文更新了Swift3、Alamofire4.5.0的代码版本,OC可以用AFNetworking)。

当我们上传图片通常还需要带参数,Alamofire不像AF一样具有封装好的带参数上传图片的方法,但是可以通过其他方法拼接参数,代码中会有相应注释。

如下图,我已经写好了调用相机和相册的界面,如果不会使用相机相册,请看我之前写过的一篇文章:http://www.jianshu.com/p/ab98f2fe2734

我分别给取消按钮,拍照按钮,相册按钮设置了tag值,对应的点击方法如下(changeView是上图所示的灰色透明界面以及灰色界面上层界面):

func buttonClickedAction(sender: UIButton) {

switch sender.tag {

case 204:

//取消点击

changeView.removeFromSuperview()

case 205:

//拍照点击

changeView.removeFromSuperview()

if UIImagePickerController.isSourceTypeAvailable(.Camera) {

let picker = UIImagePickerController()

picker.sourceType = .Camera

picker.delegate = self

picker.allowsEditing = true

self.presentViewController(picker, animated: true, completion: nil)

}

else

{

self.noticeOnlyText("无法使用相机", autoClear: true, autoClearTime: 1)

}

case 206:

//相册点击

//调用相册功能,打开相册

changeView.removeFromSuperview()

let picker = UIImagePickerController()

picker.sourceType = .PhotoLibrary

picker.delegate = self

picker.allowsEditing = true

self.presentViewController(picker, animated: true, completion: nil)

default:

break

}

}

做了上述点击事件后,点击相机拍照后或者相册进行选择后就可得到照片选择器

选择完成我们就可以用相机协议(UIImagePickerControllerDelegate,UINavigationControllerDelegate)中的imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])方法获取图片

下面的内容就直接在代码中解释:

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {

//获取info的类型

let type: String = (info[UIImagePickerControllerMediaType] as! String)

//如果选择的类型是图片

if type == "public.image"

{

//修正图片的位置(因为有时候上传的图片有颠倒,所以要修正一下,方法在后面)

let image = self.fixOrientation((info[UIImagePickerControllerOriginalImage] as! UIImage))

//****************保存图片到本地

//先把图片转成NSData(这里压缩图片到0.5,图片过大会造成上传时间太久或失败)

let data = UIImageJPEGRepresentation(image, 0.5)

//Home目录

let homeDirectory = NSHomeDirectory()

let documentPath = homeDirectory + "/Documents"

//文件管理器

let fileManager: NSFileManager = NSFileManager.defaultManager()

//把刚刚图片转换的data对象拷贝至沙盒中 并保存为image.png

do {

try fileManager.createDirectoryAtPath(documentPath, withIntermediateDirectories: true, attributes: nil)

}

catch let error {

print(error)

}

fileManager.createFileAtPath(documentPath.stringByAppendingString("/image.png"), contents: data, attributes: nil)

//得到选择后沙盒中图片的完整路径

let filePath: String = String(format: "%@%@", documentPath, "/image.png")

// print("filePath:" + filePath)

//开始上传图片

pleaseWait()

//upLoadImageURL:上传地址

Alamofire.upload(.POST, upLoadImageURL , multipartFormData: { multipartFormData in

let lastData = NSData(contentsOfFile: filePath)

//图片二进制作为参数值,file作为参数名(参数名必须与后台一致)

multipartFormData.appendBodyPart(data: lastData!, name: "file", fileName: "image.png", mimeType: "image/png")

//拼接其他参数(可以拼接多个参数,我这里需要传一个user_id的参数)

multipartFormData.appendBodyPart(data: crrentUser!.user_id.dataUsingEncoding(NSUTF8StringEncoding)!, name: "user_id" )

}, encodingCompletion: { response in

//让选择器消失掉

picker.dismissViewControllerAnimated(true, completion: nil)

switch response {

case .Success(let upload, _, _):

upload.responseJSON(completionHandler: { (response) in

self.clearAllNotice()

if let json = response.result.value{

let code = json.objectForKey("code") as! String

// print(code)

//我这里上传成功后后台会返回code=200

if code == "200"{

self.headImageView.image = UIImage(data: data!)

let data = json.objectForKey("data") as! String

crrentUser!.head_img = data

}

}

})

case .Failure(let encodingError):

print(encodingError)

}

})

}

}

func fixOrientation(aImage: UIImage) -> UIImage {

// No-op if the orientation is already correct

if aImage.imageOrientation == .Up {

return aImage

}

// We need to calculate the proper transformation to make the image upright.

// We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.

var transform: CGAffineTransform = CGAffineTransformIdentity

switch aImage.imageOrientation {

case .Down, .DownMirrored:

transform = CGAffineTransformTranslate(transform, aImage.size.width, aImage.size.height)

transform = CGAffineTransformRotate(transform, CGFloat(M_PI))

case .Left, .LeftMirrored:

transform = CGAffineTransformTranslate(transform, aImage.size.width, 0)

transform = CGAffineTransformRotate(transform, CGFloat(M_PI_2))

case .Right, .RightMirrored:

transform = CGAffineTransformTranslate(transform, 0, aImage.size.height)

transform = CGAffineTransformRotate(transform, CGFloat(-M_PI_2))

default:

break

}

switch aImage.imageOrientation {

case .UpMirrored, .DownMirrored:

transform = CGAffineTransformTranslate(transform, aImage.size.width, 0)

transform = CGAffineTransformScale(transform, -1, 1)

case .LeftMirrored, .RightMirrored:

transform = CGAffineTransformTranslate(transform, aImage.size.height, 0)

transform = CGAffineTransformScale(transform, -1, 1)

default:

break

}

// Now we draw the underlying CGImage into a new context, applying the transform

// calculated above.

//这里需要注意下CGImageGetBitmapInfo,它的类型是Int32的,CGImageGetBitmapInfo(aImage.CGImage).rawValue,这样写才不会报错

let ctx: CGContextRef = CGBitmapContextCreate(nil, Int(aImage.size.width), Int(aImage.size.height), CGImageGetBitsPerComponent(aImage.CGImage), 0, CGImageGetColorSpace(aImage.CGImage), CGImageGetBitmapInfo(aImage.CGImage).rawValue)!

CGContextConcatCTM(ctx, transform)

switch aImage.imageOrientation {

case .Left, .LeftMirrored, .Right, .RightMirrored:

// Grr...

CGContextDrawImage(ctx, CGRectMake(0, 0, aImage.size.height, aImage.size.width), aImage.CGImage)

default:

CGContextDrawImage(ctx, CGRectMake(0, 0, aImage.size.width, aImage.size.height), aImage.CGImage)

}

// And now we just create a new UIImage from the drawing context

let cgimg: CGImageRef = CGBitmapContextCreateImage(ctx)!

let img: UIImage = UIImage(CGImage: cgimg)

return img

}

将各种类型文件上传服务器封装

Swift3后Alamofire也更新了,下面是用Alamofire4.5.0版本封装的,拷贝即可使用

import UIKit

import Alamofire

enum tbUploadType: String {

///纯文本

case textOnly = "text/plain"

///HTML文档

case html = "text/html"

///XHTML文档

case xhtml = "application/xhtml+xml"

///gif图片

case gif = "image/gif"

///jpeg图片

case jpeg = "image/jpeg"

///png图片

case png = "image/png"

///mpeg动画

case mpeg = "video/mpeg"

///任意的二进制数据

case any = "application/octet-stream"

///PDF文档

case pdf = "application/pdf"

///Word文件

case word = "application/msword"

///RFC 822形式

case rfc822 = "message/rfc822"

///HTML邮件的HTML形式和纯文本形式,相同内容使用不同形式表示

case alternative = "multipart/alternative"

///使用HTTP的POST方法提交的表单

case urlencoded = "application/x-www-form-urlencoded"

///使用HTTP的POST方法提交的表单,但主要用于表单提交时伴随文件上传的场合

case formdata = "multipart/form-data"

}

class TBUploadDataManager: NSObject {

public static let share = TBUploadDataManager()

private override init() {}

/// 上传文件

///

/// - Parameters:

/// - data: 二进制流

/// - parameters: 参数字典数组

/// - hostUrl: 服务器地址

/// - withName: 与后台协商的名字

/// - fileName: 文件名

/// - type: 上传文件类型

/// - comparBlock: 将结果返回的闭包

public func uploadLocalData(data: Data,

parameters:[String:String]?,

hostUrl:String,

withName:String,

fileName: String,

type:tbUploadType,

comparBlock:@escaping (SessionManager.MultipartFormDataEncodingResult) -> Void){

Alamofire.upload(

multipartFormData: { multipartFormData in

multipartFormData.append(data, withName: withName, fileName: fileName, mimeType: type.rawValue)

if parameters != nil{

for parameter in parameters!{

multipartFormData.append(parameter.value.data(using: .utf8)!, withName: parameter.key)

}

}

},

to: hostUrl,

encodingCompletion: { encodingResult in

//把encodingResult返回出去

comparBlock(encodingResult)

}

)

}

}

调用方法

let imagedata = UIImagePNGRepresentation(UIImage(named: "1111")!)

TBUploadDataManager.share.uploadLocalData(data: imagedata!, parameters: ["id":"12345"], hostUrl: "地址", withName: "协商名字", fileName: "1111.png", type: tbUploadType.png, comparBlock: { encodingResult in

switch encodingResult {

case .success(let upload, _, _):

upload.responseJSON { response in

debugPrint(response)

if let json = response.result.value{

print(json)

}

//

//成功要干什么

}

case .failure(let encodingError):

print(encodingError)

//失败要干什么

}

})

swift文件服务器,Swift3一行代码将各种类型文件上传到服务器相关推荐

  1. php文件上传绕过mime类型,文件上传限制绕过技巧

    严正声明:本文仅限于技术讨论,严禁用于其他用途. 简介 文件上传漏洞是web安全中经常利用到的一种漏洞形式.一些web应用程序中允许上传图片,文本或者其他资源到指定的位置,文件上传漏洞就是利用这些可以 ...

  2. bottle 文件服务器,python bottle 框架基础教程:文件上传 | linux系统运维

    文件上传,需要注意的是前端html的form表单中,要添加 enctype="multipart/form-data"属性,否则无法上传文件.在后端,用request.files方 ...

  3. 【Java报错】MultipartFile 类型文件上传 Current request is not a multipart request 问题处理(postman添加MultipartFile)

    1. 问题描述 一个正常的Excel文档上传并导入其数据的接口开发,首先出现问题的是 Doc 文档,我使用的是: <dependency><groupId>com.github ...

  4. hadoop上传文件java_hadoop入门之通过java代码实现将本地文件上传到hadoop的文件系统...

    第一步:首先搭建java的编译环境.创建一个Java Project工程,名为upload. 第二步:选中所需的Jar包. 选中JRE System Library 选择BuildPath Confi ...

  5. 文件上传至服务器cpu,文件服务器构建指南

    处理器篇 再说一次,文件服务器的主要用途是存储,而不是处理能力,也不是在游戏中获得很高的帧速率.就家庭文件服务器而言,包括处理器在内的其他所有部件都应该让位于硬盘.机箱和电源.重申一下,文件服务器不需 ...

  6. postman代码没有问题,但是文件上传失败

    1. 问题分析 postman临时上传非工作区的文件是可以的,但是当你关掉postman再重启,postman会帮你记住选择的文件,但是永远没办法成功上传上去,原因是因为该文件不在工作区内. 2. 解 ...

  7. 上传文件的php代码,PHP实现大文件上传源代码

    PHP实现大文件上传源代码 PHP 基础教程 PHP 是一种创建动态交互性站点的`强有力的服务器端脚本语言. PHP 是免费的,并且使用广泛. 以下是小编为大家搜索整理的PHP实现大文件上传源代码,希 ...

  8. python requests form data_Python requests模块 multipart/form-data类型文件上传

    ------WebKitFormBoundarytqaIYaLC4rpPRnpl Content-Disposition: form-data;   name="isNew" 1 ...

  9. 文件上传到服务器 完整代码,上传文件到服务器 前端+后台代码

    不是原创,但有必要记录一下,免得每次都找的很辛苦 html Select a File to Upload js function fileSelected() { var file = docume ...

最新文章

  1. 使用分层实现业务处理(二)
  2. 【备忘录】使用mongodb,报db.collection is not a function
  3. 网络爬虫中进行数据抓取
  4. Qt 图形视图框架中的事件处理和传播
  5. java getclass 相等_Java判断2个List集合是否相等(不考虑元素的顺序)
  6. 与ai计算机专业大学排名,全球大学计算机科学与人工智能排名:卡耐基梅隆大学居首...
  7. [家里蹲大学数学杂志]第036期泛函分析期末试题
  8. JavaFX UI控件教程(五)之Radio Button
  9. java hessian rmi_RMI,socket,rpc,hessian,http比较
  10. 在计算机发展的早期 计算机主要用于,全国网络统考《计算机应用基础》选择题复习...
  11. Java对象分配原理
  12. ArrayList的容量
  13. java 多态与重载的区别_java实现多态 方法的重写和重载的区别
  14. ECShop如何设置默认的配送方式和支付方式
  15. 华为进军美国受挫:竟被美运营商巨头临时放鸽子
  16. 【2019杭电多校第七场1006=HDU6651】Final Exam(思维转换)
  17. C语言UDP socket编程
  18. iphone12是双卡双待吗
  19. 你的MP3中不能缺少的231首歌
  20. 主播入门到精通培训实操手册全套资料(共300份)

热门文章

  1. Python怎么利用多核cpu
  2. TVM darknet yolov3算子优化与量化代码的配置方法
  3. GStreamer跨平台多媒体框架
  4. 空间点像素索引(二)
  5. CentOS7环境搭建使用PhpStorm上传代码
  6. 【嵌入式】openmv与stm32的串口通信
  7. Linux 忘记登录密码?破解系统登陆密码
  8. JAVA第二次验证设计性实验报告
  9. LoadRunner11录制脚本出现的问题
  10. Linux学习之三-Linux系统的一些重要配置文件