Swift - HTTP网络操作库Alamofire使用详解2(文件上传)
作者:hangge | 2015-12-08 10:03
相关文章系列:(文章代码均已升级至Swift3)
Swift - HTTP网络操作库Alamofire使用详解1(配置,以及数据请求)
[当前文章] Swift - HTTP网络操作库Alamofire使用详解2(文件上传)
Swift - HTTP网络操作库Alamofire使用详解3(文件下载,断点续传)
Swift - HTTP网络操作库Alamofire使用详解4(用户权限认证)
Swift - HTTP网络操作库Alamofire使用详解1(配置,以及数据请求)
[当前文章] Swift - HTTP网络操作库Alamofire使用详解2(文件上传)
Swift - HTTP网络操作库Alamofire使用详解3(文件下载,断点续传)
Swift - HTTP网络操作库Alamofire使用详解4(用户权限认证)
六,使用Alamofire进行文件上传
File
Data
Stream
MultipartFormData
Data
Stream
MultipartFormData
2,使用文件流的形式上传文件
let fileURL = Bundle.main.url(forResource: "hangge", withExtension: "zip")
Alamofire.upload(fileURL!, to: "http://www.hangge.com/upload.php")
.responseJSON { response in
debugPrint(response)
}
附:服务端代码(upload.php)
<?php
/** php 接收流文件
* @param String $file 接收后保存的文件名
* @return boolean
*/
function receiveStreamFile($receiveFile){
$streamData = isset($GLOBALS['HTTP_RAW_POST_DATA'])? $GLOBALS['HTTP_RAW_POST_DATA'] : '';
if(empty($streamData)){
$streamData = file_get_contents('php://input');
}
if($streamData!=''){
$ret = file_put_contents($receiveFile, $streamData, true);
}else{
$ret = false;
}
return $ret;
}
//定义服务器存储路径和文件名
$receiveFile = $_SERVER["DOCUMENT_ROOT"]."/uploadFiles/hangge.zip";
$ret = receiveStreamFile($receiveFile);
echo json_encode(array('success'=>(bool)$ret));
?>
如何在上传时附带上文件名?
有时我们在文件上传的同时还会想要附带一些其它参数,比如文件名。这样服务端接收到文件后,就可以根据我们传过来的文件名来保存。实现这个其实很简单,客户端和服务端分别做如下修改。
有时我们在文件上传的同时还会想要附带一些其它参数,比如文件名。这样服务端接收到文件后,就可以根据我们传过来的文件名来保存。实现这个其实很简单,客户端和服务端分别做如下修改。
- 客户端:将文件名以参数的形式跟在链接后面。比如:http://hangge.com/upload.php?fileName=image1.png
- 服务端:通过 $_GET["fileName"] 得到这个参数,并用其作为文件名保存。
3,上传时附带上传进度
let fileURL = Bundle.main.url(forResource: "hangge", withExtension: "zip")
Alamofire.upload(fileURL!, to: "http://www.hangge.com/upload.php")
.uploadProgress { progress in // main queue by default
print("当前进度: \(progress.fractionCompleted)")
}
.responseJSON { response in
debugPrint(response)
}
可以看到控制台不断输出已上传的进度(1则表示上传完毕):

4,上传MultipartFormData类型的文件数据(类似于网页上Form表单里的文件提交)
(1)上传两个文件
let fileURL1 = Bundle.main.url(forResource: "hangge", withExtension: "png")
let fileURL2 = Bundle.main.url(forResource: "hangge", withExtension: "zip")
Alamofire.upload(
multipartFormData: { multipartFormData in
multipartFormData.append(fileURL1!, withName: "file1")
multipartFormData.append(fileURL2!, withName: "file2")
},
to: "http://www.hangge.com/upload2.php",
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
debugPrint(response)
}
case .failure(let encodingError):
print(encodingError)
}
}
)
附:服务端代码(upload2.php)
<?
move_uploaded_file($_FILES["file1"]["tmp_name"],
$_SERVER["DOCUMENT_ROOT"]."/uploadFiles/" . $_FILES["file1"]["name"]);
move_uploaded_file($_FILES["file2"]["tmp_name"],
$_SERVER["DOCUMENT_ROOT"]."/uploadFiles/" . $_FILES["file2"]["name"]);
?>
(2)文本参数与文件一起提交(文件除了可以使用fileURL,还可以上传NSData类型的文件数据)
//字符串
let strData = "hangge.com".data(using: String.Encoding.utf8)
//数字
let intData = String(10).data(using: String.Encoding.utf8)
//文件1
let path = Bundle.main.url(forResource: "hangge", withExtension: "png")!
let file1Data = try! Data(contentsOf: path)
//文件2
let file2URL = Bundle.main.url(forResource: "hangge", withExtension: "zip")
Alamofire.upload(
multipartFormData: { multipartFormData in
multipartFormData.append(strData!, withName: "value1")
multipartFormData.append(intData!, withName: "value2")
multipartFormData.append(file1Data, withName: "file1",
fileName: "h.png", mimeType: "image/png")
multipartFormData.append(file2URL!, withName: "file2")
},
to: "http://www.hangge.com/upload2.php",
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
debugPrint(response)
}
case .failure(let encodingError):
print(encodingError)
}
}
)
附:服务端代码(upload2.php)
<?
$value1 = $_POST["value1"];
$value2 = $_POST["value2"];
move_uploaded_file($_FILES["file1"]["tmp_name"],
$_SERVER["DOCUMENT_ROOT"]."/uploadFiles/" . $_FILES["file1"]["name"]);
move_uploaded_file($_FILES["file2"]["tmp_name"],
$_SERVER["DOCUMENT_ROOT"]."/uploadFiles/" . $_FILES["file2"]["name"]);
?>
全部评论(7)
航哥你好,我按照这种方法传数据到后台,但后台收到的全是空数据,这是咋回事。
站长回复:你是使用文章里哪种上传方式:文件流?还是MultipartFormData?
航哥,想请教一个问题: 场景是:我有一个表单,填写好表单内容,上传本地的多张图片,然后我点击提交按钮发送提交请求,我在parameters中添加输入的内容传了过去,我多张图片该怎么在这个请求中上传呢?救急,先在此谢过了,后台直接request.files 获取表单请求中所有文件
站长回复:想要内容和文件一起上传的话使用MultipartFormData,也就是文章最后的那个样例。
航哥你好,小弟最近在练习多选图片上传,现在使用PhotoKit想Post出去,使用Alamofire适合吗?
站长回复:你好。当然可以使用Alamofire来实现多个图片同时上传(文章第四点)。
要注意的是你用PhotoKit获取图片后,要先把图片保存到临时目录下。再使用Alamofire上传保存在临时目录下的这些图片。
不能直接通过PhotoKit获取的图片路径上传。参考我原来写的这篇文章:Swift - 从相册中选择照片并上传(使用UIImagePickerController)
对的,航哥,我是用UIImagePickerController选的照片,然后我让
let imagePicked = info[UIImagePickerControllerOriginalImage] as! UIImage
let imageUrl = info[UIImagePickerControllerReferenceURL] as! NSURL
再用Alamofire的appendBodyPart(fileURL: imageUrl, name: imageName)上传,报The file URL does not point to a file URL错误,接口指定是这种传法,请指教一下用Swift怎么获得fileURL,菜鸟一个,望指教,不胜感激!!
站长回复:这种方式确实是无法上传照片的。即使得到fileURL也上传不了。我这边刚好在写相关文章,大概周五发。你可以关注下。
hangge,我要从图库里随机选择一张图片上传,我怎样获得这张图片的fileURL和name呢?
站长回复:你是用UIImagePickerController选择图片吗,选择后使用photeKit可以获取到图片的路径和名字。你可以上网查下photeKit的用法,后面我也会写篇相关文章的。
hangge 我需要往服务器穿图片,但是需要填入parameters,如果使用upload,没有传parameters的地方。如果使用request,又不知道怎么传图片。 求hangge解答啊~
站长回复:参数,图片都要传得话可以使用MultipartFormData,就是本文中的第四点(2)样例。
站长,请问一下。 我用Alamofire.upload(
.POST,
"http://www.zhekd.com/admin.php",
multipartFormData: { multipartFormData in
// multipartFormData.appendBodyPart(data: idData!, name: "id")
multipartFormData.appendBodyPart(data: authorData!, name: "article_author")
multipartFormData.appendBodyPart(data: telData!, name: "article_tel")
multipartFormData.appendBodyPart(data: adImageData!, name: "article_ad_image")
multipartFormData.appendBodyPart(data: twoImageData!, name: "article_two_image")
multipartFormData.appendBodyPart(data: tittleData!, name: "article_ad_title")
multipartFormData.appendBodyPart(data: descData!, name: "article_ad_desc")
multipartFormData.appendBodyPart(data: urlData!, name: "article_ad_url")
},
上传数据到服务器,但是测试了下,文字的都能上传,图片的无法上传,显示错误是[Result]: FAILURE: Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 1." UserInfo={NSDebugDescription=Invalid value around character 1.}
是为什么啊,是服务器端出了问题还是ios端出的问题?
站长回复:应该是ios端的的问题,你贴个完整的代码我看下。我主要看下图片数据怎么来的(比如adImageData)