您的位置:首页 > 移动开发 > IOS开发

iOS开发 使用NSURLConnection实现图片上传

2017-07-17 13:49 441 查看
一.原理

1.图片上传使用的是POST请求

2.请求体:通常把要上传的数据保存到请求体(HTTPBody)中,将图片编码到POST请求体中,通过请求数据一起发送到服务器

3.请求头:通常存放内容类型(Content-Type)和请求体数据总长度(Content-Length)

4.图片上传的请求体和请求头非常难写,格式要求非常严格,出一点错误都会造成上传失败或者请求数据失败

二.格式

1.请求头格式:

Content-Length(key)    请求体数据总长度(value)

Content-Type(key)        multipart/form-data; boundary=--本地上传标识字符串(不能包含中文)(value)

2.请求体格式:

/******************图片参数**********************/

--本次上传标识字符串(分隔符号,以--开头,后边是自定义的分割标识符)

\r\n (换行)

Content-Disposition: form-data; name="参数名"; filename="上传文件名"

\r\n (换行)

Content-Type: 上传文件类型

\r\n (换行)

\r\n (换行,注意这里要换行,必不可少)

要上传的二进制数据(参数值) 

\r\n (换行)

/*******************其他参数*********************************/

--本次上传标识字符串(分隔符号,以--开头,后边是自定义的分割标识符)

\r\n (换行)

Content-Disposition: form-data; name="参数名"

\r\n (换行)

\r\n (换行,注意这里要换行,必不可少)

要上传的值(参数值) 

\r\n (换行)

--本次上传标识字符串--(结束符)



三.参数解释

1.图片参数

//分割符号,以"--"开头,后边是自定义的分割标识符
-- Boundary+72D4CD655314C423
//这里注明服务器接受图片的参数(服务器指定参数名称)及服务器上保存图片的文件名
Content-Disposition: form-data; name="file"; filename="001.png"
//图片类型png或者jpeg
Content-Type:image/png
//编码方式(PS:一直没弄懂)
Content-Transfer-Encoding: binary
// 这里空一行,必须不可少
*空一行*
// 图片数据部分
... contents of boris.png ...
//分割符号右面以"--"结尾,表示结束
--Boundary+72D4CD655314C423--

2.其他参数

-Boundary+2D4CD655314C423
Content-Disposition: form-data; name="userId"
*空一行*
254
--Boundary+2D4CD655314C423
Content-Disposition: form-data; name="shopId"
*空一行*
18718

四.实现代码

// 上传文件
class func urlConnectionUpload(_ url: String, params: Dictionary<String, AnyObject>?, image: UIImage, success: (_ data: Data?) -> Void, fail: (_ error: NSError?) -> Swift.Void) {
if url.isEmpty {
fail(NSError(domain: "url为空", code: 404, userInfo: [:]))
return
}
var imageData: Data = Data()
var imageFormat: String = String()
if let data = UIImagePNGRepresentation(image) {
imageData = data
imageFormat = "Content-Type: image/png"
} else {
imageData = UIImageJPEGRepresentation(image, 1.0)!
imageFormat = "Content-Type: image/jpeg"
}
var request = URLRequest(url: URL(string: url)!)
// 设置请求方式
request.httpMethod = "POST"

// 设置请求体
var httpBody = Data()
/******************params参数*****************/
if let param = params {
for (key, value) in param {
// 分割符号,以"--"开头,后边是自定义的分割表示符
httpBody.append(strTodata("--WL")!)
// 换行
httpBody.append(strTodata("\r\n")!)
// key
httpBody.append(strTodata("Content-Disposition: form-data; name=\"\(key)\"")!)
// 换行
httpBody.append(strTodata("\r\n")!)
// 换行
httpBody.append(strTodata("\r\n")!)
// value
httpBody.append(strTodata(value as! String)!)
// 换行
httpBody.append(strTodata("\r\n")!)
}
}
/******************文件参数*****************/
// 分割符号,以"--"开头,后边是自定义的分割表示符
httpBody.append(strTodata("--WL")!)
// 换行
httpBody.append(strTodata("\r\n")!)
// 这里注明服务器接受图片的参数(服务器指定参数名称)及服务器上保存图片的文件名
httpBody.append(strTodata("Content-Disposition: form-data; name=\"file\"; filename=\"001.png\"")!)
// 换行
httpBody.append(strTodata("\r\n")!)
// 图片类型png或者jpeg Content-Type: image/png
httpBody.append(strTodata(imageFormat)!)
// 换行
httpBody.append(strTodata("\r\n")!)
// 这里需要在空一行,必须不可少
httpBody.append(strTodata("\r\n")!)
// 图片Data
httpBody.append(imageData)
// 换行
httpBody.append(strTodata("\r\n")!)
// 参数结束
httpBody.append(strTodata("--WL--")!)

request.httpBody = httpBody

// 设置请求头信息
request.setValue("multipart/form-data; boundary=WL", forHTTPHeaderField: "Content-Type")
request.setValue(String(httpBody.count), forHTTPHeaderField: "Content-Length")
request.timeoutInterval = 60
NSURLConnection.sendAsynchronousRequest(request, queue: OperationQueue()) { (response, data, error) in
if error != nil {
print(error!)
} else {
do {
let dic = try JSONSerialization.jsonObject(with: data!, options: [.mutableContainers])
print(dic)
} catch {
print(error)
}
}
}
}

方法strTodata:

// String to Data
func strTodata(_ str: String) -> Data? {
return str.data(using: .utf8)
}

5.注意:

一定要检查好 \r\n 有没有添加好

6.补充

部门文件的MIMEType:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐