使用Swift 3将参数和数据发送到Web服务器
我想弄清楚如何从iPhone发送照片到我的networking服务器。
我还需要发送包含照片大小的参数,文件名以及与参数数据相同请求的其他附加信息。
下面的代码是在我想的正确的轨道上,但我在哪里把参数数据称为params
:
let params: Array<String> = [aI.filename, String(aI.size), String(aI.dateTime.year), String(aI.dateTime.month), String(aI.dateTime.day), String(aI.dateTime.hour), String(aI.dateTime.minute), String(aI.dateTime.second), String(aI.dateTime.millisecond)] var serverURL = URL(string: "http://192.168.0.23/upload.php"); var req = NSMutableURLRequest(url: serverURL!, cachePolicy: NSURLRequest.CachePolicy.useProtocolCachePolicy, timeoutInterval: 60.0); //Set request to post req.httpMethod = "POST"; //Set content type req.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type"); let task = URLSession.sharedSession().dataTaskWithRequest(req){ data, response, error in if error != nil{ print("Error -> \(error)") return } do { let result = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? [String:AnyObject] print("Result -> \(result)") } catch { print("Error -> \(error)") } } task.resume() return task
虽然一些答案把我推向了正确的方向,但他们仍然不适合我的项目,所以我继续googlesearch,我设法在下面的文章中find我所需要的: http : //swiftdeveloperblog.com/image-upload -例/
我需要asynchronous地创buildHTTP请求并使用会话,这在问题中没有指定,因为问题仅仅是如何在一个请求中同时发送几个参数和数据。
这样做时称为Multipart Form Data
。
我不得不修改文章中的代码,使其适用于我的应用程序,所以我在下面分享我的Swift 3代码:
触发代码
let params = [ "filename" : chunkOwner.filename , "size" : String(describing: chunkOwner.size) , "year" : String(chunkOwner.dateTime.year) , "month" : String(chunkOwner.dateTime.month) , "day" : String(chunkOwner.dateTime.day) , "hour" : String(chunkOwner.dateTime.hour) , "minute" : String(chunkOwner.dateTime.minute) , "second" : String(chunkOwner.dateTime.second) , "millisecond" : String(chunkOwner.dateTime.millisecond) , ] uploadChunk(url: URL(string: "http://192.168.0.23/upload.php")!, data: photoData, params: params)
上传代码:
func uploadData(url: URL, data: Data!, params: [String: String]) { let cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringLocalCacheData; let request = NSMutableURLRequest(url: url, cachePolicy: cachePolicy, timeoutInterval: 6.0); request.httpMethod = "POST"; let boundary = generateBoundaryString() request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type") if(data == nil) { return; } request.httpBody = createBodyWithParameters(parameters: params, filePathKey: "file", data: data, boundary: boundary) //myActivityIndicator.startAnimating(); let task = URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in if error != nil { print("error=\(error)") return } // You can print out response object print("******* response = \(response)") // Print out reponse body let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue) print("****** response data = \(responseString!)") do { let json = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary print(json) }catch { //if you recieve an error saying that the data could not be uploaded, //make sure that the upload size is set to something higher than the size print(error) } } task.resume() } func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, data: Data!, boundary: String) -> Data { var body = Data(); if parameters != nil { for (key, value) in parameters! { body.appendString(string: "--\(boundary)\r\n") body.appendString(string: "Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n") body.appendString(string: "\(value)\r\n") } } let mimetype = "text/csv" body.appendString(string: "--\(boundary)\r\n") body.appendString(string: "Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(parameters!["filename"]!)\"\r\n") body.appendString(string: "Content-Type: \(mimetype)\r\n\r\n") body.append(data) body.appendString(string: "\r\n") body.appendString(string: "--\(boundary)--\r\n") return body } func generateBoundaryString() -> String { return "Boundary-\(NSUUID().uuidString)" }
在您的.swift
文件的底部还包含以下代码:
extension Data { mutating func appendString(string: String) { append(string.data(using: .utf8)!) } }
而对于PHP上传脚本,我做了一些改变,现在看起来像这样:
<?php $target_dir = "/var/www/html/uploads";if(!file_exists($target_dir)){ mkdir($target_dir, 0777, true); } $target_dir = $target_dir . "/" . basename($_FILES["file"]["name"]); echo count("size: ".$_FILES["file"]["tmp_name"]); if (move_uploaded_file($_FILES["file"]["tmp_name"], $target_dir)){ echo json_encode([ "Message" => "The file ". basename( $_FILES["file"]["name"]). " has been uploaded.", "Status" => "OK", ]); } else { echo json_encode([ "Message" => "Sorry, there was an error uploading your file.", "Status" => "Error", ]); } ?>
重要的提示:
如果您的服务器php文件
php.ini
被configuration为接受比您尝试上传的数据更小的文件,您的应用程序将无法上传数据。例如:如果
php.ini
被configuration为接受2 MB,那么任何大于2 MB的上传将被忽略,您的应用程序将收到一个响应,说有什么地方出错了。要在
php.ini
更改文件大小接受度,您需要查找名为upload_max_filesize
和post_max_size
的variables,并将其更改为您的系统需要的任何文件大小。
你可以把它们放到httpBody或httpBodyStream中 (通过使用NSInputStream)
但不要忘记为服务器协议转换参数(例如xml,json或具有自定义格式的二进制数据)。
对于您的内容types(application / x-www-form-urlencoded),您可以在wikipedia中find格式:
keyName=value&keyName2=value2
键和值应该包含URLPathAllowedCharacterSet,要实现它,你可以使用stringByAddingPercentEncodingWithAllowedCharacters 。
要将KeyValuestring转换为NSData,可以使用dataUsingEncoding方法。
我在Swift3
分享你使用NSURLConnection
发送数据的一种方法
您的url
var serverURL = URL(string: "http://192.168.0.23/upload.php")
你的参数是这样的,只是与服务器人讨论你需要传递数据的参数然后像下面那样给你的参数赋值
serverparameter1 = \(value to post)& serverparameter2 = \(value to post2).......
用你的参数,我喜欢这个看看
let params = "filename= \(aI.filename)&size = \(String(aI.size))& dateTimeYear =\(String(aI.dateTime.year))&dateTimeMonth =\(String(aI.dateTime.month))& dateTimeDay =\(String(aI.dateTime.day))&dateTimeHour =\(String(aI.dateTime.hour))&dateTimeMinute =\(String(aI.dateTime.minute))&dateTimeSecond =\(String(aI.dateTime.second))&dateTimeMilliSecond=\(String(aI.dateTime.millisecond))"
将您的照片数据转换为Base64String,如下所示
var base64String: NSString! let myImage = UIImage(named:"image.png") let imageData = UIImageJPEGRepresentation(myImage, 0.9) base64String = imageData!.base64EncodedString(options: NSData.Base64EncodingOptions.endLineWithLineFeed) as NSString! print(base64String)
然后作为stringParameter传递
&ImageDataStr = \(base64String)
那么最终的url看起来就像
\(serverURL)/\(params)
要么
\(serverURL)/Upload?\(params)
一步一步的请求
var serverURL = URL(string: "http://192.168.0.23/upload.php") let params = "filename= \(aI.filename)&size = \(String(aI.size))& dateTimeYear =\(String(aI.dateTime.year))&dateTimeMonth =\(String(aI.dateTime.month))& dateTimeDay =\(String(aI.dateTime.day))&dateTimeHour =\(String(aI.dateTime.hour))&dateTimeMinute =\(String(aI.dateTime.minute))&dateTimeSecond =\(String(aI.dateTime.second))&dateTimeMilliSecond=\(String(aI.dateTime.millisecond))&photoDataStr = \(base64String)" var status:NSString = "\(serverURL)/Upload?\(params)" as NSString status = status.addingPercentEscapes(using: String.Encoding.utf8.rawValue)! as NSString let url = URL(string: status as String)! let request = URLRequest(url: url, cachePolicy:NSURLRequest.CachePolicy.reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 600) // need synchronous
在这里你会得到responseData
var response:URLResponse? var responseD:Data = try! NSURLConnection.sendSynchronousRequest(request, returning:&response)
最后使该BinaryData可读
// save to string - the result came from the Server call var serverResults:NSString = NSString(data: responseD, encoding: String.Encoding.utf8.rawValue)! print(serverResults)
例如你的结果
if serverResults.range(of: "RESULT>APPROVED").location != NSNotFound { return "Data posted" } else { return "Failed to post" }