swift开发笔记:Alamofire 4.5
来源:互联网 发布:起个好的淘宝店铺名字 编辑:程序博客网 时间:2024/06/06 02:31
前言:
对于Alamofire文件上传,网上大多数的教程的Alamofire版本都是在3.0。但是Alamofire在4.0的版本上作出了重大更新,特别在文件上传出现了很多变化,网上的代码直接copy会有错误。另外,网上的大部分代码并不提供后台,对于并不了解文件后台接收的swift学习爱好者来说是头疼的。其次,对于视频上传的网上中文资料少之又少,大多数都是一些图片(小文件)上传,没有尝试上传视频这样的大文件。闲暇之时写一篇关于Alamofire最新的文件上传的教程,希望大家喜欢。
客户端
Info.plist
ViewController.swift
//// ViewController.swift// uploadDemo//// Created by liwenban on 2017/8/21.// Copyright © 2017年 hellomiao. All rights reserved.//import UIKitimport AVFoundationimport MobileCoreServicesimport AssetsLibraryimport AVKitimport Alamofireimport MediaPlayerclass ViewController: UIViewController,UIImagePickerControllerDelegate, UINavigationControllerDelegate { //设置标志,用于标识上传那种类型文件(图片/视频) var flag = "" //设置服务器地址 let uploadURL = "http://www.hellomiao.cn/hellomiao/upload.php" override func viewDidLoad() { super.viewDidLoad() } //按钮事件:上传图片 @IBAction func uploadImage(_ sender: Any) { photoLib() } //按钮事件:上传视频 @IBAction func uploadVideo(_ sender: Any) { videoLib() } //图库 - 照片 func photoLib(){ // flag = "图片" //判断设置是否支持图片库 if UIImagePickerController.isSourceTypeAvailable(.photoLibrary){ //初始化图片控制器 let picker = UIImagePickerController() //设置代理 picker.delegate = self //指定图片控制器类型 picker.sourceType = UIImagePickerControllerSourceType.photoLibrary //弹出控制器,显示界面 self.present(picker, animated: true, completion: { () -> Void in }) }else{ print("读取相册错误") } } //图库 - 视频 func videoLib(){ flag = "视频" if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) { //初始化图片控制器 let imagePicker = UIImagePickerController() //设置代理 imagePicker.delegate = self //指定图片控制器类型 imagePicker.sourceType = .photoLibrary; //只显示视频类型的文件 imagePicker.mediaTypes = [kUTTypeMovie as String] //不需要编辑 imagePicker.allowsEditing = false //弹出控制器,显示界面 self.present(imagePicker, animated: true, completion: nil) } else { print("读取相册错误") } } //选择成功后代理 func imagePickerController(_ picker: UIImagePickerController,didFinishPickingMediaWithInfo info: [String : Any]) { if flag == "视频" { //获取选取的视频路径 let videoURL = info[UIImagePickerControllerMediaURL] as! URL let pathString = videoURL.path print("视频地址:\(pathString)") //图片控制器退出 self.dismiss(animated: true, completion: nil) let outpath = NSHomeDirectory() + "/Documents/\(Date().timeIntervalSince1970).mp4" //视频转码 self.transformMoive(inputPath: pathString, outputPath: outpath) }else{ //flag = "图片" //获取选取后的图片 let pickedImage = info[UIImagePickerControllerOriginalImage] as! UIImage //转成jpg格式图片 guard let jpegData = UIImageJPEGRepresentation(pickedImage, 0.5) else { return } //上传 self.uploadImage(imageData: jpegData) //图片控制器退出 self.dismiss(animated: true, completion:nil) } } //上传图片到服务器 func uploadImage(imageData : Data){ Alamofire.upload( multipartFormData: { multipartFormData in //采用post表单上传 // 参数解释: //withName:和后台服务器的name要一致 ;fileName:可以充分利用写成用户的id,但是格式要写对; mimeType:规定的,要上传其他格式可以自行百度查一下 multipartFormData.append(imageData, withName: "file", fileName: "123456.jpg", mimeType: "image/jpeg") //如果需要上传多个文件,就多添加几个 //multipartFormData.append(imageData, withName: "file", fileName: "123456.jpg", mimeType: "image/jpeg") //...... },to: uploadURL,encodingCompletion: { encodingResult in switch encodingResult { case .success(let upload, _, _): //连接服务器成功后,对json的处理 upload.responseJSON { response in //解包 guard let result = response.result.value else { return } print("json:\(result)") } //获取上传进度 upload.uploadProgress(queue: DispatchQueue.global(qos: .utility)) { progress in print("图片上传进度: \(progress.fractionCompleted)") } case .failure(let encodingError): //打印连接失败原因 print(encodingError) } }) } //上传视频到服务器 func uploadVideo(mp4Path : URL){ Alamofire.upload( //同样采用post表单上传 multipartFormData: { multipartFormData in multipartFormData.append(mp4Path, withName: "file", fileName: "123456.mp4", mimeType: "video/mp4") //服务器地址 },to: uploadURL,encodingCompletion: { encodingResult in switch encodingResult { case .success(let upload, _, _): //json处理 upload.responseJSON { response in //解包 guard let result = response.result.value else { return } print("json:\(result)") } //上传进度 upload.uploadProgress(queue: DispatchQueue.global(qos: .utility)) { progress in print("视频上传进度: \(progress.fractionCompleted)") } case .failure(let encodingError): print(encodingError) } }) } /// 转换视频 /// /// - Parameters: /// - inputPath: 输入url /// - outputPath:输出url func transformMoive(inputPath:String,outputPath:String){ let avAsset:AVURLAsset = AVURLAsset(url: URL.init(fileURLWithPath: inputPath), options: nil) let assetTime = avAsset.duration let duration = CMTimeGetSeconds(assetTime) print("视频时长 \(duration)"); let compatiblePresets = AVAssetExportSession.exportPresets(compatibleWith: avAsset) if compatiblePresets.contains(AVAssetExportPresetLowQuality) { let exportSession:AVAssetExportSession = AVAssetExportSession.init(asset: avAsset, presetName: AVAssetExportPresetMediumQuality)! let existBool = FileManager.default.fileExists(atPath: outputPath) if existBool { } exportSession.outputURL = URL.init(fileURLWithPath: outputPath) exportSession.outputFileType = AVFileTypeMPEG4 exportSession.shouldOptimizeForNetworkUse = true; exportSession.exportAsynchronously(completionHandler: { switch exportSession.status{ case .failed: print("失败...\(String(describing: exportSession.error?.localizedDescription))") break case .cancelled: print("取消") break; case .completed: print("转码成功") let mp4Path = URL.init(fileURLWithPath: outputPath) self.uploadVideo(mp4Path: mp4Path) break; default: print("..") break; } }) } }}
后台代码
upload.php
<?phpheader('Content-type: text/json; charset=UTF-8' );$response = array();// 文件类型限制 "file"名字必须和iOS客户端上传的name一致if ($_FILES["file"]["error"] > 0) { $response ["error"] = "错误代码".$_FILES["file"]["error"]; echo json_encode($response);} else { //获取传入的文件名 $fillName = $_FILES['file']['name']; //以 "." 为界对文件名分割,并存入数组 $dotArray = explode('.', $fillName); //获取文件格式 $type = end($dotArray); // - - - - - //小技巧:客户端传入的文件名,除了文件的格式要对之外,文件名部分是可以随意填写。 //经过点分割后,就可以将文件名和文件格式分开,分开后下标为0的就是文件名,部分,这时候就间接实现了传参,获得用户的id $userId = $dotArray[0]; // - - - - //设置存入的文件名(路径) $path = "../res/".$userId.'.'.$type; // 从临时目录复制到目标目录 move_uploaded_file($_FILES["file"]["tmp_name"],$path); //校验传入后文件是否存在 if (file_exists($path)){ $response ['success']= 1; //json格式返回 echo json_encode($response); }else { $response ['success'] = 0; echo json_encode($response); }}?>
注意事项
服务器是php环境的web服务器。php对上传文件的大小、超时时间有限制。因此再测试上传视频的时候,会出现上传失败是正常现象。
解决办法: php.ini
可以通过 “command + F”搜索以下字段:file_uploads = on ;是否允许通过HTTP上传文件的开关。默认为ON即是开upload_tmp_dir ;文件上传至服务器上存储临时文件的地方,如果没指定就会用系统默认的临时文件夹upload_max_filesize = 8m ;望文生意,即允许上传文件大小的最大值。默认为2Mpost_max_size = 8m ;指通过表单POST给PHP的所能接收的最大值,包括表单里的所有值。默认为8M一般地,设置好上述四个参数后,上传<=8M的文件是不成问题,在网络正常的情况下。但如果要上传>8M的大体积文件,只设置上述四项还一定能行的通。近一步配置以下的参数max_execution_time = 600 ;每个PHP页面运行的最大时间值(秒),默认30秒max_input_time = 600 ;每个PHP页面接收数据所需的最大时间,默认60秒memory_limit = 8m ;每个PHP页面所吃掉的最大内存,默认8M把上述参数修改后,在网络所允许的正常情况下,就可以上传大体积文件了max_execution_time = 600max_input_time = 600memory_limit = 32mfile_uploads = onupload_tmp_dir = /tmpupload_max_filesize = 32mpost_max_size = 32m
简书同步更新:http://www.jianshu.com/p/749f05625240
阅读全文
0 0
- swift开发笔记:Alamofire 4.5
- swift开发之Alamofire
- iOS开发 - swift通过Alamofire实现https通信
- Swift网络库Alamofire
- Swift-解读Alamofire
- 五、Swift Alamofire入门
- Alamofire-Swift Networking网络库
- Alamofire-Swift Networking网络库
- Alamofire-Swift Networking网络库
- Swift 第三方库 - Alamofire
- Swift网络请求库Alamofire
- swift利用Alamofire上传图片
- 【IOS开发】swift版的AFNETworking之Alamofire的用法 图片上传
- Swift 中AFNetworking 的替代方案 Alamofire
- Swift - Alamofire - GET/POST/upload 的使用
- Swift-->Http网络请求(NSURLSession, Alamofire)
- swift 数据请求Alamofire的使用
- [iOS]Swift-Alamofire 4.0 使用初探
- 浅谈HTTP协议
- 静态方法,静态代码块
- PHP-Redis中文文档
- cf 550c Divisibility by Eight 【规律】
- JAVA-反射机制(1)
- swift开发笔记:Alamofire 4.5
- 算法提高 ADV-68 企业奖金发放
- 【vue+axios】一个项目学会前端实现登录拦截 时间 2017-02-17 12:06:19 Github 原文 https://github.com/superman66/vue-axios
- systemd详解(CentOS 7)
- Python 之正则表达式 使用介绍
- 大型网站核心要素和高性能架构
- ccpc网络赛 E
- 算法提高 ADV-69 质因数
- 我的开始