我正在尝试使用json数据上传图像。我刚跟着here并实施了这个机制。但我收到了错误
{ status code: 400, headers {
"Cache-Control" = "no-cache, no-store, max-age=0, must-revalidate";
Connection = close;
"Content-Language" = en;
"Content-Length" = 1033;
"Content-Type" = "text/html;charset=utf-8";
Date = "Wed, 27 Jan 2016 10:44:34 GMT";
Expires = 0;
Pragma = "no-cache";
Server = "Apache-Coyote/1.1";
"X-Content-Type-Options" = nosniff;
"X-XSS-Protection" = "1; mode=block";
} }`
以下是完整的HTTP请求
Content-Type: multipart/form-data;boundary=Boundary_123456789
Authorization: Basic bihdwbcIUkbcdwjnoNOn
User-Agent: Jersey/2.21.1 (HttpUrlConnection 1.8.0_45)
MIME-Version: 1.0
Host: localhost:8080
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 3526
--Boundary_123456789
Content-Type: application/json
Content-Disposition: form-data; name="userDTO"
{"id":"id","name":"name","age":23}
--Boundary_123456789
Content-Type: image/png
Content-Disposition: form-data; filename="sample-image2.png"; modification-date="Fri, 22 Jan 2016 04:56:48 GMT"; size=3308; name="file"
‰PNG
<Binary data>
--Boundary_123456789—
以下是我的实施
func addUser(completion: (message: String?, error: String?) -> Void) -> NSURLSessionDataTask {
// create the request
let request = createRequest()
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
print(response) // 400 Error is printed here
}
task.resume()
return task
}
func createRequest () -> NSURLRequest {
let param = [
"id": "id",
"name": "name",
"age": 23] // build your dictionary however appropriate
let boundary = generateBoundaryString()
let url = NSURL(string: SERVERURL)!
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.addValue("Basic \(base64LoginString())", forHTTPHeaderField: "Authorization")
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let path1 = NSBundle.mainBundle().pathForResource("userImage", ofType: "png") as String!
request.HTTPBody = createBodyWithParameters(param, paths: [path1], boundary: boundary)
return request
}
func createBodyWithParameters(json: [String:AnyObject], paths: [String]?, boundary: String) -> NSData {
let body = NSMutableData()
let key = "userDTO"
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Type: application/json")
body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
var requestBody = NSData()
do {
requestBody = try NSJSONSerialization.dataWithJSONObject(json, options: NSJSONWritingOptions(rawValue:0))
} catch (let e) {
print(e)
}
body.appendData(requestBody)
//body.appendString("\(json)\r\n")
if paths != nil {
for path in paths! {
let url = NSURL(fileURLWithPath: path)
let data = NSData(contentsOfURL: url)!
let mimetype = mimeTypeForPath(path)
let fileName = "sample-image23.png"
let date = "Fri, 22 Jan 2016 04:56:48 GMT"
let name = "file"
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Type: \(mimetype)\r\n\r\n")
body.appendString("Content-Disposition: form-data; filename=\"\(fileName)\"; modification-date=\"\(date)\"; size=3308; name=\"\(name)\"\r\n")
body.appendData(data)
body.appendString("\r\n")
}
}
body.appendString("--\(boundary)--\r\n")
return body
}
func generateBoundaryString() -> String {
return "Boundary-\(NSUUID().UUIDString)"
}
func mimeTypeForPath(path: String) -> String {
let url = NSURL(fileURLWithPath: path)
let pathExtension = url.pathExtension
if let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension! as NSString, nil)?.takeRetainedValue() {
if let mimetype = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() {
return mimetype as String
}
}
return "application/octet-stream";
}
也是扩展名
extension NSMutableData {
func appendString(string: String) {
let data = string.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
appendData(data!)
}
}
我想我在json格式中犯了一些错误。有人可以帮忙吗?谢谢!
答案 0 :(得分:1)
看来,上传图片不是你的问题 - 就我所见,它成功了。您应该意识到,上传图像与JSON无关。相反,以您期望的格式(JSON)获得响应可能就是您所寻求的。因此,如果您需要获取其主体为JSON的响应,则应通过设置相应的Accept
标头明确说明此情况。例如:
Accept: application/json
并在代码中:
request.setValue("application/json", forHTTPHeaderField: "Accept")
当您收到回复时,您还应首先检查响应的状态代码,然后检查Content-Type
标题(分别为响应'MIMEType
属性),该标题应符合您的预期:{{ 1}}。
如果内容类型不符合您的预期,您可以尝试使用其他“响应序列化程序” - 每个都适合解析其他内容类型,例如: application/json
等,如你所愿。
修改强>
服务器回应提示,多部分请求的第二部分格式不正确。看看它是如何组成的:
text/plain
现在,仔细观察,我们可以看到第二个标题 body.appendString("--\(boundary)\r\n")
body.appendString("Content-Type: \(mimetype)\r\n\r\n")
body.appendString("Content-Disposition: form-data; filename='sample-image23.png'; modification-date='Fri, 22 Jan 2016 04:56:48 GMT'; size=3308; name='file'\r\n")
body.appendData(data)
body.appendString("\r\n")
将以两个 Content-Type
分隔 - 但是还有另一个标题。标题应该只用一个 CRLF
分隔。
然后,最后一个标题必须用两个 CRLF
分隔。
建议修复:
CRLF
(编辑:删除了错误的描述)
编辑2:
这些行中还缺少 body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; filename='sample-image23.png'; modification-date='Fri, 22 Jan 2016 04:56:48 GMT'; size=3308; name='file'\r\n")
body.appendString("Content-Type: \(mimetype)\r\n\r\n")
body.appendData(data)
body.appendString("\r\n")
,高于这一行:
CRLF
你看到了这个问题? let key = "userDTO"
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Type: application/json")
body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
没有尾随Content-Type
!
答案 1 :(得分:0)
此代码段将帮助您使用 POST 方法将 UIImage 文件上传到网络服务。
func uploadImageOne(){
var imageData = UIImagePNGRepresentation(exampleImageView.image)
if imageData != nil{
var request = NSMutableURLRequest(URL: NSURL(string:"Your URL")!)
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
var boundary = NSString(format: "---------------------------14737809831466499882746641449")
var contentType = NSString(format: "multipart/form-data; boundary=%@",boundary)
// println("Content Type \(contentType)")
request.addValue(contentType, forHTTPHeaderField: "Content-Type")
var body = NSMutableData.alloc()
// Title
body.appendData(NSString(format: "\r\n--%@\r\n",boundary).dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData(NSString(format:"Content-Disposition: form-data; name=\"title\"\r\n\r\n").dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData("Hello World".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!)
// Image
body.appendData(NSString(format: "\r\n--%@\r\n", boundary).dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData(NSString(format:"Content-Disposition: form-data; name=\"profile_img\"; filename=\"img.jpg\"\\r\n").dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData(NSString(format: "Content-Type: application/octet-stream\r\n\r\n").dataUsingEncoding(NSUTF8StringEncoding)!)
body.appendData(imageData)
body.appendData(NSString(format: "\r\n--%@\r\n", boundary).dataUsingEncoding(NSUTF8StringEncoding)!)
request.HTTPBody = body
var returnData = NSURLConnection.sendSynchronousRequest(request, returningResponse: nil, error: nil)
var returnString = NSString(data: returnData!, encoding: NSUTF8StringEncoding)
println("returnString \(returnString)")
}
}