Related
I want to post image with parameters to server with url session, Here what I try -
var groupImg: UIImage?
var grupId: String = ""
var grupName: String = ""
var creator: String = "xahiw"
var lati = "30.6425°N"
var long = "76.8173°E"
and here's the code on the action of button
#IBAction func onClickSubmitBtn(_ sender: Any) {
let url = URL(string: "http://example/api/create")!
var request = URLRequest(url: url)
request.setValue("Application/json", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
let parameters: [String: Any] = [
"name": grupName,
"category": grupId,
"picture": groupImg!,
"createdBy": creator,
"lat": lati,
"lng": long
]
request.httpBody = parameters.percentEncoded()
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data,
let response = response as? HTTPURLResponse,
error == nil else {
print("error", error ?? "Unknown error")
return
}
guard (200 ... 299) ~= response.statusCode else {
print("statusCode should be 2xx, but is \(response.statusCode)")
print("response = \(response)")
return
}
let responseString = String(data: data, encoding: .utf8)
print("responseString = \(String(describing: responseString))")
}
task.resume()
}
extension Dictionary {
func percentEncoded() -> Data? {
return map { key, value in
let escapedKey = "\(key)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
let escapedValue = "\(value)".addingPercentEncoding(withAllowedCharacters: .urlQueryValueAllowed) ?? ""
return escapedKey + "=" + escapedValue
}
.joined(separator: "&")
.data(using: .utf8)
}
}
extension CharacterSet {
static let urlQueryValueAllowed: CharacterSet = {
let generalDelimitersToEncode = ":#[]#"
let subDelimitersToEncode = "!$&'()*+,;="
var allowed = CharacterSet.urlQueryAllowed
allowed.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
return allowed
}()
}
but i unable to post data i get the status code -- 400 when i click on button, can anyone tell me how to do this, is it done with different way (upload image with parameters )
You can use a simple function to create a body for your request.
func createBodyWithParameters(parameters: [String: String], filePathKey: String?, imageDataKey: Data?, boundary: String) -> Data {
var body = Data();
for (key, value) in parameters {
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.appendString("\(value)\r\n")
}
let filename = "image_name.jpg"
let mimetype = "image/jpg"
body.appendString("--\(boundary)\r\n")
if let filePath = filePathKey, let imageData = imageDataKey {
body.appendString("Content-Disposition: form-data; name=\"\(filePath)\"; filename=\"\(filename)\"\r\n")
body.appendString("Content-Type: \(mimetype)\r\n\r\n")
body.append(imageData)
body.appendString("\r\n")
body.appendString("--\(boundary)--\r\n")
}
return body
}
and assign it to the request body.
request.httpBody = createBodyWithParameters(parameters: ["key":"Value"], filePathKey: "file", imageDataKey: imageData, boundary: "Boundary-\(NSUUID().uuidString)");
For appending string to the data, you can use an extension like this.
extension Data {
mutating func appendString(_ string: String) {
let data = string.data(using: String.Encoding.utf8, allowLossyConversion: true)
append(data!)
}
}
class func request(withImages path:APIMethods, method:URLMethod, token : String?, headers:[String:String]?, parameters: [String:Any]?,imageNames : [String], images:[Data], completion: #escaping(Any?, Error?, Bool)->Void) {
var stringUrl = “abc.com”
if method == .get, let lastPath = parameters?.values.first as? String {
stringUrl += lastPath
}else{
stringUrl += token ?? ""
}
// generate boundary string using a unique per-app string
let boundary = UUID().uuidString
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
print("\n\ncomplete Url :-------------- ",stringUrl," \n\n-------------: complete Url")
guard let url = URL(string: stringUrl) else { return }
var request = URLRequest(url: url)
request.httpMethod = method.rawValue
if headers != nil{
print("\n\nHeaders :-------------- ",headers as Any,"\n\n --------------: Headers")
for (key, value) in headers! {
request.setValue(value, forHTTPHeaderField: key)
}
}
// Set Content-Type Header to multipart/form-data
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
var data = Data()
if parameters != nil{
for(key, value) in parameters!{
data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
data.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: .utf8)!)
data.append("\(value)".data(using: .utf8)!)
}
}
for (index,imageData) in images.enumerated() {
data.append("\r\n--\(boundary)\r\n".data(using: .utf8)!)
data.append("Content-Disposition: form-data; name=\"\(imageNames[index])\"; filename=\"\(imageNames[index])\"\r\n".data(using: .utf8)!)
data.append("Content-Type: image/jpeg\r\n\r\n".data(using: .utf8)!)
data.append(imageData)
}
data.append("\r\n--\(boundary)--\r\n".data(using: .utf8)!)
session.uploadTask(with: request, from: data, completionHandler: { data, response, error in
if let checkResponse = response as? HTTPURLResponse{
if checkResponse.statusCode == 200{
guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: [JSONSerialization.ReadingOptions.allowFragments]) else {
completion(nil, error, false)
return
}
let jsonString = String(data: data, encoding: .utf8)!
print("\n\n---------------------------\n\n"+jsonString+"\n\n---------------------------\n\n")
print(json)
completion(json, nil, true)
}else{
guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) else {
completion(nil, error, false)
return
}
let jsonString = String(data: data, encoding: .utf8)!
print("\n\n---------------------------\n\n"+jsonString+"\n\n---------------------------\n\n")
print(json)
completion(json, nil, false)
}
}else{
guard let data = data, let json = try? JSONSerialization.jsonObject(with: data, options: []) else {
completion(nil, error, false)
return
}
completion(json, nil, false)
}
}).resume()
}
extension Data {
mutating func append(_ string: String, using encoding: String.Encoding = .utf8) {
if let data = string.data(using: encoding) {
append(data)
}
}
}
Checkout the code for single image upload but not able to upload the multiple images in an array under same key.
IN BELOW CODE ,
It is working perfect when I am sending one image to the server.
-> I want to find answer for the multiple images in array without using alamofire or other third party library.
func imageUploadRequest(IMAGE_ARRAY: [UIImage] , uploadUrl: NSURL) {
myloader.showLoader(controller: self)
let param = ["title":"ds","category_id":"5","description":"gdfjghjdsfgksd","user_id":"66","color":"red"]
let request = NSMutableURLRequest(url:uploadUrl as URL)
request.httpMethod = "POST"
let boundary = generateBoundaryString()
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
//let imageData = UIImageJPEGRepresentation(imageView.imageOrientation, 0.1)
for item in IMAGE_ARRAY
{
let imageData = item.jpegData(compressionQuality: 0.01)
if(imageData==nil) { return; }
request.httpBody = createBodyWithParameters(parameters: param as [String : Any], filePathKey: "files[]", cv : imageData! as NSData, boundary: boundary) as Data
}
// myActivityIndicator.startAnimating();
let task = URLSession.shared.dataTask(with: request as URLRequest,
completionHandler: {
(data, response, error) -> Void in
if let data = data {
DispatchQueue.main.async { // Update UI
self.myloader.removeLoader(controller: self)
let decoder = JSONDecoder()
let obj = try! decoder.decode(GetResponse_Otp.self, from: data)
}
}
})
task.resume()
}
func createBodyWithParameters(parameters: [String: Any]?, filePathKey: String?, cv: NSData, boundary: String) -> NSData {
let body = NSMutableData();
if parameters != nil {
for (key, value) in parameters! {
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.appendString("\(value)\r\n")
}
}
let filename = "\(Date().timeIntervalSince1970).jpeg"
let mimetype = "image/png"
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
body.appendString("Content-Type: \(mimetype)\r\n\r\n")
body.append(cv as Data)
body.appendString("\r\n")
body.appendString("--\(boundary)--\r\n")
return body
}
func generateBoundaryString() -> String {
return "Boundary-\(NSUUID().uuidString)"
}
// extension for impage uploading
}
You need to change your key name to KEY_NAME[] add array [] in your key and make sure every time the file name is different or you can try this too:
(Date().timeIntervalSince1970).jpeg
to make sure that the name is different everytime.
func imageUploadRequest(ARRAY_OF_IMAGES: [ANY] , uploadUrl: NSURL) {
myloader.showLoader(controller: self)
let param = ["user_id":fetchString(key: "userId"), "career_level":UnwarppingValue(value: btnCarrer.title(for: .normal)),"education":UnwarppingValue(value: btnEducation.title(for: .normal)),"cur_location":txtFldLocation.text!,"cur_position":txtFldCurrentPosition.text!,"cur_employee":txtFldCurrentEmployee.text!,"experience": UnwarppingValue(value: btnExperience.title(for: .normal)),"industry":UnwarppingValue(value: btnIndustry.title(for: .normal))] as [String : Any]
let request = NSMutableURLRequest(url:uploadUrl as URL)
request.httpMethod = "POST"
let boundary = generateBoundaryString()
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
//let imageData = UIImageJPEGRepresentation(imageView.imageOrientation, 0.1)
for item in IMAGE_ARRAY
{
let imageData = item.jpegData(compressionQuality: 0.01)
if(imageData==nil) { return; }
request.httpBody = createBodyWithParameters(parameters: param as [String : Any], filePathKey: "KEY_NAME[]", cv : imageData! as NSData, boundary: boundary) as Data
}
// myActivityIndicator.startAnimating();
let task = URLSession.shared.dataTask(with: request as URLRequest,
completionHandler: {
(data, response, error) -> Void in
if let data = data {
DispatchQueue.main.async { // Update UI
self.myloader.removeLoader(controller: self)
let decoder = JSONDecoder()
let obj = try! decoder.decode(GetResponse_ProfileOverViewDetails.self, from: data)
guard obj.response?.result == "1" else{
showToast(message: obj.response?.msg ?? "Something Went Wrong", vc: self, normalColor: false)
return
}
if let userPic = obj.response?.data?[0].pic {
saveStringInDefault(value: userPic, key: "userPic")
}else {
saveStringInDefault(value: "", key: "userPic")
}
showToast(message: obj.response?.msg ?? "Something Went Wrong", vc: self, normalColor: false)
}
}
})task.resume()
}
func createBodyWithParameters(parameters: [String: Any]?, filePathKey: String?, cv: NSData, boundary: String) -> NSData {
let body = NSMutableData();
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 filename = HERE->(Date().timeIntervalSince1970).jpeg
let mimetype = "image/png"
body.appendString(string: "--\(boundary)\r\n")
body.appendString(string: "Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
body.appendString(string: "Content-Type: \(mimetype)\r\n\r\n")
body.append(cv as Data)
body.appendString(string: "\r\n")
body.appendString(string: "--\(boundary)--\r\n")
return body
}
func generateBoundaryString() -> String {
return "Boundary-\(NSUUID().uuidString)"
}
// extension for impage uploading
}
Check i edit the code in caps.
i am new in ios. i did like that but i am getting response from server "Required MultipartFIle" Parameter 'file' is not present.
1) addUser method i am calling inside my button event.
func addUser(completion: (message: String?, error: String?) -> Void) -> NSURLSessionDataTask {
// create the request method called here
let request = createRequest()
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) { data, response, error in
if error != nil{
print("#----->response",response)
return// 400 Error is printed here
}
do {
if let responseDictionary = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? NSDictionary {
print("responseDictionary == \(responseDictionary)")
}
} catch {
print(error)
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("responseString = \(responseString)")
}
}
task.resume()
return task
}
func createRequest () -> NSURLRequest {
let param = [
"clientName" : self.projectClientNameField.text!,
"clientAddress" : self.projectAddressField.text!,
"clientNumber" : self.projectClientContactField.text!,
"projectName" : self.projectNameField.text!,
"projectDesc" : self.projectDetailsField.text!,
"startDate" : "",
"endDate" : "",
]
let boundary = generateBoundaryString()
let url = NSURL(string: "MYURL")!
let request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.setValue("*/*", forHTTPHeaderField: "Accept")
request.setValue("100-continue", forHTTPHeaderField: "Expect")
//request.setValue("image/jpeg", forHTTPHeaderField: "Content-Type")
let imageData = UIImagePNGRepresentation(image.image!)
if imageData==nil{
print("#-->imageData",imageData)
}
request.HTTPBody = createBodyWithParameters(param, imageDataKey: imageData!, boundary: boundary)
print("request -->",request)
NSLog("%#", [request]);
return request
}
func createBodyWithParameters(json: [String:AnyObject], imageDataKey: NSData, boundary: String) -> NSData {
let body = NSMutableData()
let key = "project"
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))
print("#--->",requestBody)
} catch (let e) {
print(e)
}
body.appendData(requestBody)
let mimetype = "image/png"
let fileName = "suppliers.png"
let name = "file"
//body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"file\"; file=\"\(fileName)\"\r\n")
body.appendString("Content-Type: \(mimetype)\r\n\r\n")
body.appendData(imageDataKey)
body.appendString("\r\n")
print(body)
body.appendString("--\(boundary)--\r\n")
return body
}
func generateBoundaryString() -> String {
return "------------------------\(NSUUID().UUIDString)"
}
response for server is :
{
error = "Bad Request";
exception = "org.springframework.web.bind.MissingServletRequestParameterException";
message = "Required MultipartFile parameter 'file' is not present";
path = "/project/create";
status = 400;
timestamp = 1468475579881;
}
can anybody please resolve this??
Here is full code to upload images(you can use multiple images)to upload on server.
You can use below method.
You have to just pass paramDictionary and URL.
func createBodyWithParameters(parameters: NSMutableDictionary?,boundary: String) -> NSData {
let body = NSMutableData()
if parameters != nil {
for (key, value) in parameters! {
if(value is String || value is NSString){
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.appendString("\(value)\r\n")
}
else if(value is [UIImage]){
var i = 0;
for image in value as! [UIImage]{
let filename = "image\(i).jpg"
let data = UIImageJPEGRepresentation(image,1);
let mimetype = mimeTypeForPath(filename)
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(key)\"; filename=\"\(filename)\"\r\n")
body.appendString("Content-Type: \(mimetype)\r\n\r\n")
body.appendData(data!)
body.appendString("\r\n")
i++;
}
}
}
}
body.appendString("--\(boundary)--\r\n")
// NSLog("data %#",NSString(data: body, encoding: NSUTF8StringEncoding)!);
return body
}
func generateBoundaryString() -> String {
return "Boundary-\(NSUUID().UUIDString)"
}
func mimeTypeForPath(path: String) -> String {
let pathExtension = path.pathExtension
var stringMimeType = "application/octet-stream";
if let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension!, nil)?.takeRetainedValue() {
if let mimetype = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue() {
stringMimeType = mimetype as NSString as String
}
}
return stringMimeType;
}
func createRequest (param : NSMutableDictionary , strURL : String) -> NSURLRequest {
let boundary = generateBoundaryString()
let url = NSURL(string: strURL)
let request = NSMutableURLRequest(URL: url!)
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.HTTPMethod = "POST"
request.HTTPBody = createBodyWithParameters(param, boundary: boundary)
return request
}
It won't work, how to send an image from an iOS Swift app to my PHP server?
#IBAction func upload(sender: UIButton) {
var imageData = UIImageJPEGRepresentation(img.image, 90)
// println(imageData)
let url = NSURL(string:"http://www.i35.club.tw/old_tree/test/uplo.php")
//let cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData
//var request = NSMutableURLRequest(URL: url, cachePolicy: cachePolicy, timeoutInterval: 10)
var request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
// set Content-Type in HTTP header
let boundaryConstant = "----------V2ymHFg03esomerandomstuffhbqgZCaKO6jy";
let contentType = "multipart/form-data; boundary=" + boundaryConstant
NSURLProtocol.setProperty(contentType, forKey: "Content-Type", inRequest: request)
request.HTTPBody = imageData
// set data
//var dataString = "adkjlkajfdadf"
//let requestBodyData = (dataString as NSString).dataUsingEncoding(NSUTF8StringEncoding)
//request.HTTPBody = requestBodyData
//
request.addValue(contentType, forHTTPHeaderField: "Content-Type")
request.addValue("multipart/form-data", forHTTPHeaderField: "Accept")
//
// set content length
//NSURLProtocol.setProperty(requestBodyData.length, forKey: "Content-Length", inRequest: request)
var response: NSURLResponse? = nil
var error: NSError? = nil
let reply = NSURLConnection.sendSynchronousRequest(request, returningResponse:&response, error:&error)
let results = NSString(data:reply!, encoding:NSUTF8StringEncoding)
println("API Response: \(results)")
}
//take photo
func imagePickerController(picker: UIImagePickerController!, didFinishPickingImage image: UIImage!, editingInfo: NSDictionary!) {
var selectedImage : UIImage = image
img.image = selectedImage
UIImageWriteToSavedPhotosAlbum(selectedImage, nil, nil, nil)
self.dismissViewControllerAnimated(true, completion: nil)
}
I have taken the photo by user's choice and written code for swift 2 and iOS9
func imageUploadRequest(imageView imageView: UIImageView, uploadUrl: NSURL, param: [String:String]?) {
//let myUrl = NSURL(string: "http://192.168.1.103/upload.photo/index.php");
let request = NSMutableURLRequest(URL:uploadUrl);
request.HTTPMethod = "POST"
let boundary = generateBoundaryString()
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let imageData = UIImageJPEGRepresentation(imageView.image!, 1)
if(imageData==nil) { return; }
request.HTTPBody = createBodyWithParameters(param, filePathKey: "file", imageDataKey: imageData!, boundary: boundary)
//myActivityIndicator.startAnimating();
let task = NSURLSession.sharedSession().dataTaskWithRequest(request,
completionHandler: {
(data, response, error) -> Void in
if let data = data {
// You can print out response object
print("******* response = \(response)")
print(data.length)
// you can use data here
// Print out reponse body
let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
print("****** response data = \(responseString!)")
let json = try!NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers) as? NSDictionary
print("json value \(json)")
//var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: &err)
dispatch_async(dispatch_get_main_queue(),{
//self.myActivityIndicator.stopAnimating()
//self.imageView.image = nil;
});
} else if let error = error {
print(error.description)
}
})
task.resume()
}
func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, imageDataKey: NSData, boundary: String) -> NSData {
let body = NSMutableData();
if parameters != nil {
for (key, value) in parameters! {
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.appendString("\(value)\r\n")
}
}
let filename = "user-profile.jpg"
let mimetype = "image/jpg"
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
body.appendString("Content-Type: \(mimetype)\r\n\r\n")
body.appendData(imageDataKey)
body.appendString("\r\n")
body.appendString("--\(boundary)--\r\n")
return body
}
func generateBoundaryString() -> String {
return "Boundary-\(NSUUID().UUIDString)"
}
}// extension for impage uploading
extension NSMutableData {
func appendString(string: String) {
let data = string.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
appendData(data!)
}
}
--------- following code for the php side
<?php
$firstName = $_POST["firstName"];
$lastName = $_POST["lastName"];
$userId = $_POST["userId"];
$target_dir = "media";
if(!file_exists($target_dir))
{
mkdir($target_dir, 0777, true);
}
$target_dir = $target_dir . "/" . basename($_FILES["file"]["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",
"userId" => $_REQUEST["userId"]
]);
} else {
echo json_encode([
"Message" => "Sorry, there was an error uploading your file.",
"Status" => "Error",
"userId" => $_REQUEST["userId"]
]);
}
To upload image with parameters use this code,
// Your method to upload image with parameters to server.
func uploadImageOne(){
var imageData = UIImagePNGRepresentation(imageView.image)
if imageData != nil{
var request = NSMutableURLRequest(URL: NSURL(string:"Enter 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)")
}
}
My updated code for Swift 3
func uploadImage() {
let url = URL(string: "YOUR SERVER URL");
let request = NSMutableURLRequest(url: url!);
request.httpMethod = "POST"
let boundary = "Boundary-\(NSUUID().uuidString)"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
var retreivedImage: UIImage? = nil
//Get image
do {
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let readData = try Data(contentsOf: URL(string: "file://\(documentsPath)/myImage")!)
retreivedImage = UIImage(data: readData)
addProfilePicView.setImage(retreivedImage, for: .normal)
}
catch {
print("Error while opening image")
return
}
let imageData = UIImageJPEGRepresentation(retreivedImage!, 1)
if (imageData == nil) {
print("UIImageJPEGRepresentation return nil")
return
}
let body = NSMutableData()
body.append(NSString(format: "\r\n--%#\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format: "Content-Disposition: form-data; name=\"api_token\"\r\n\r\n" as NSString).data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format: (UserDefaults.standard.string(forKey: "api_token")! as NSString)).data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format: "\r\n--%#\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format:"Content-Disposition: form-data; name=\"profile_img\"; filename=\"testfromios.jpg\"\r\n").data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format: "Content-Type: application/octet-stream\r\n\r\n").data(using: String.Encoding.utf8.rawValue)!)
body.append(imageData!)
body.append(NSString(format: "\r\n--%#\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
request.httpBody = body as Data
let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: {
(data, response, error) -> Void in
if let data = data {
// do what you want in success case
} else if let error = error {
print(error.localizedDescription)
}
})
task.resume()
}
And PHP side code you can take from #VinodJoshi answer.
According to the blogpost of Sergey Kargopolov (http://swiftdeveloperblog.com/image-upload-example/) and his video (https://youtu.be/HqxeyS961Uk) here is my code that worked perfectly in Swift 5.
It will upload a picture to the directory specified in the php script (further down) and it will name the picture according to the imgKey given. In my example, it will upload the imageToUpload of myImageUploadRequest to the directory "wp-content/Images". The param dictionary is not necessarily needed. This could very well be written more efficiently but maybe it is a start for someone :)
func myImageUploadRequest(imageToUpload: UIImage, imgKey: String) {
let myUrl = NSURL(string: "https://yourdomain/uploadPicture.php");
let request = NSMutableURLRequest(url:myUrl! as URL);
request.httpMethod = "POST";
let param = [
"firstName" : "name",
"lastName" : "name",
"userId" : "42"
]
let boundary = generateBoundaryString()
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let imageData = imageToUpload.jpegData(compressionQuality: 1)
if imageData == nil {
return
}
request.httpBody = createBodyWithParameters(parameters: param, filePathKey: "file", imageDataKey: imageData! as NSData, boundary: boundary, imgKey: imgKey) as Data
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
print("error=\(error!)")
return
}
//print response
//print("response = \(response!)")
// print reponse body
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("response data = \(responseString!)")
}
task.resume()
}
func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, imageDataKey: NSData, boundary: String, imgKey: String) -> NSData {
let body = NSMutableData();
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 filename = "\(imgKey).jpg"
let mimetype = "image/jpg"
body.appendString(string: "--\(boundary)\r\n")
body.appendString(string: "Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
body.appendString(string: "Content-Type: \(mimetype)\r\n\r\n")
body.append(imageDataKey as Data)
body.appendString(string: "\r\n")
body.appendString(string: "--\(boundary)--\r\n")
return body
}
func generateBoundaryString() -> String {
return "Boundary-\(NSUUID().uuidString)"
}
}
extension NSMutableData {
func appendString(string: String) {
let data = string.data(using: String.Encoding.utf8, allowLossyConversion: true)
append(data!)
}
}
The server sided php (PHP/7.3.18) code:
<?php
$firstName = $_POST["firstName"];
$lastName = $_POST["lastName"];
$userId = $_POST["userId"];
$target_dir = "wp-content/Images";
if (!file_exists($target_dir)) {
mkdir($target_dir, 0777, true);
}
$target_dir = $target_dir . "/" . basename($_FILES["file"]["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",
"userId" => $_REQUEST["userId"]
]);
}
else {
echo json_encode([
"Message" => "Sorry, there was an error uploading your file.",
"Status" => "Error",
"userId" => $_REQUEST["userId"]
]);
}
?>
Example console output:
response data = {
"Message":"The file 9B862D73-9F0B-4DD3-8FBB-452AEF2FE1CF.jpg has been uploaded.",
"Status":"OK",
"userId":"17"}
I have made function for Block method which is easy to use and this is class function so you can use anywhere in your project for example make
MVCServer.swift
NSObject class and
import Alamofire
and then write this function in this class
func postImageRequestWithURL(withUrl strURL: String,withParam postParam: Dictionary<String, Any>,withImages imageArray:NSMutableArray,completion:#escaping (_ isSuccess: Bool, _ response:NSDictionary) -> Void)
{
Alamofire.upload(multipartFormData: { (MultipartFormData) in
// Here is your Image Array
for (imageDic) in imageArray
{
let imageDic = imageDic as! NSDictionary
for (key,valus) in imageDic
{
MultipartFormData.append(valus as! Data, withName:key as! String,fileName: "file.jpg", mimeType: "image/jpg")
}
}
// Here is your Post paramaters
for (key, value) in postParam
{
MultipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
}, usingThreshold: UInt64.init(), to: strURL, method: .post) { (result) in
switch result {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (progress) in
print("Upload Progress: \(progress.fractionCompleted)")
})
upload.responseJSON { response in
if response.response?.statusCode == 200
{
let json = response.result.value as? NSDictionary
completion(true,json!);
}
else
{
completion(false,[:]);
}
}
case .failure(let encodingError):
print(encodingError)
completion(false,[:]);
}
}
}
Now Call this Function
var ImageArray : NSMutableArray!
// Here is your post parameter
var parameters: [String:Any] = ["user_master_id" : “56”,
"first_name": “Jignesh”,
"last_name" : “Mayani”,
"email": “TestEmail#gmail.com”]
// Here is your image is in DATA formate don’t send as UIImage formate
let ImageDic = ["profile_image" : imageData!]
// Here you can pass multiple image in array i am passing just one
ImageArray = NSMutableArray(array: [ImageDic as NSDictionary])
MVCServer().postImageRequestWithURL(withUrl: "write Your URL here", withParam: parameters, withImages: ImageArray) { (isSuccess, response) in
// Your Will Get Response here
}
I would recommend to take a look at: https://github.com/sraj/Swift-SRWebClient
Sample function that worked for me:
func uploadImage(image:UIImage) {
let imageData:NSData = UIImageJPEGRepresentation(image, 100)
SRWebClient.POST("http://www.example.com/upload/")
.data(imageData, fieldName:"photo", data: ["foo":"bar","baz":"qux"])
.send({(response:AnyObject!, status:Int) -> Void in
// process success response
},failure:{(error:NSError!) -> Void in
// process failure response
})
}
You’ll notice that the above code is a slightly adjusted version of the snippets on the Swift-SRWebClient Github page. I’ve replaced NSData.dataWithData with UIImageJPEGRepresentation as the former is deprecated.
Also, don’t forget to drag SRWebClient.swift into your project folder, otherwise this won’t work :)
#IBAction func upload(sender: UIButton) {
var imageData = UIImageJPEGRepresentation(img.image, 90)
var url = NSURL(string: "http://www.i35.club.tw/old_tree/test/uplo.php")
var request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.HTTPBody = NSData.dataWithData(UIImagePNGRepresentation(imageData))
var response: NSURLResponse? = nil
var error: NSError? = nil
let reply = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error)
let results = NSString(data: reply!, encoding: NSUTF8StringEncoding)
println("API Response: \(results)")
}
Refer this link
This is great, I've been trying to pass an image using REST for a while and coouldn't format it just right and kept getting timeout errors. Using createBodyWithParameters I was able to make it work.
Here's the Swift 3 version of the code:
func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, imageDataKey: UIImage, boundary: String) -> Data {
var body = Data();
if parameters != nil {
for (key, value) in parameters! {
body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: String.Encoding.utf8)!)
body.append("\(value)\r\n".data(using: String.Encoding.utf8)!)
}
}
let filename = "user-profile.jpg"
let mimetype = "image/jpg"
body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Type: \(mimetype)\r\n\r\n".data(using: String.Encoding.utf8)!)
body.append(UIImageJPEGRepresentation(imageDataKey, 1)!)
//body.appendData(imageDataKey)
body.append("\r\n".data(using: String.Encoding.utf8)!)
body.append("--\(boundary)--\r\n".data(using: String.Encoding.utf8)!)
return body
}
Just look on that simple explanation:
Form data and multipart uploads with URLRequest
Also, to keep code up to date you can replace NSMutableData on Data. So your final code will be looks like:
func createHttpBody(parameters: [String: String]? = nil, _ boundary: String, data: Data, mimeType: String, filename: String) -> Data {
var body = Data()
let boundaryPrefix = "--\(boundary)\r\n"
if let parameters = parameters {
for (key, value) in parameters {
body.append(boundaryPrefix)
body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.append("\(value)\r\n")
}
}
body.append(boundaryPrefix)
body.append("Content-Disposition: form-data; name=\"file\"; filename=\"\(filename)\"\r\n")
body.append("Content-Type: \(mimeType)\r\n\r\n")
body.append(data)
body.append("\r\n")
body.append("--".appending(boundary.appending("--")))
return body
}
And updated extension for Data to use append method:
extension Data {
mutating func append(_ string: String) {
if let data = string.data(using: .utf8) {
append(data)
}
}
}
Also you can check this video tutorial and check source code for that tutorial.
In swift 4.1 and Xcode 9.4.1
See my Code in this blog for Upload image to server in Swift
https://markingios.blogspot.com/2018/09/upload-image-to-server-in-swift.html
Call this function like : uploadImage()
func uploadImage(){
let imageData = UIImageJPEGRepresentation(yourImage!, 1.0)//Replace your image
if imageData != nil{
var request = URLRequest(url: NSURL(string:urlString)! as URL)//Send your URL here
print(request)
request.httpMethod = "POST"
let boundary = NSString(format: "---------------------------14737809831466499882746641449")
let contentType = NSString(format: "multipart/form-data; boundary=%#",boundary)
// println("Content Type \(contentType)")
request.addValue(contentType as String, forHTTPHeaderField: "Content-Type")
var body = Data()
body.append(NSString(format: "\r\n--%#\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format:"Content-Disposition: form-data;name=\"title\"\r\n\r\n").data
(using:String.Encoding.utf8.rawValue)!)
body.append("Hello".data(using: String.Encoding.utf8, allowLossyConversion: true)!)
body.append(NSString(format: "\r\n--%#\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format:"Content-Disposition: form-data;name=\"uploaded_file\";filename=\"image.jpg\"\\r\n").data
(using:String.Encoding.utf8.rawValue)!) //Here replace your image name and file name
body.append(NSString(format: "Content-Type: image/jpeg\r\n\r\n").data(using: String.Encoding.utf8.rawValue)!)
body.append(imageData!)
body.append(NSString(format: "\r\n--%#\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
request.httpBody = body
let task = URLSession.shared.dataTask(with: request) { data, response, error in guard let data = data, error == nil
else { // check for fundamental networking error
print("error=\(String(describing: error))")
SharedClass.sharedInstance.alert(view: self, message: "\(String(describing: error!.localizedDescription))")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode == 500 {
SharedClass.sharedInstance.alert(view: self, message: "Server Error")
} else if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(String(describing: response))")
}
//This can print your response in string formate
let responseString = String(data: data, encoding: .utf8)
// let dictionary = data
// print("dictionary = \(dictionary)")
print("responseString = \(String(describing: responseString!))")
do {
self.response3 = (try JSONSerialization.jsonObject(with: data, options: []) as? [String: AnyObject])!
print(self.response3)
if (((self.response3["Response"] as? [String : Any])?["status"]) as! String == "SUCCESS") {
let message = (self.response3["Response"] as? [String : Any])?["message"] as? String
SharedClass.sharedInstance.alert(view:self, message: message)
} else {
let message = (self.response3["Response"] as? [String : Any])?["message"] as? String
SharedClass.sharedInstance.alert(view:self, message: message)
}
} catch let error as NSError {
print(error)
print(error.localizedDescription)
}
}
task.resume()
}
}
request.httpMethod = "POST" is important for upload long string or blob
func imageUpload(imageData:String){
var request:NSMutableURLRequest!
let param:String = "image=\(imageData)" // image data should be here
request = NSMutableURLRequest(url: URL(string: "www.pickmyoffers.com")!)// use your upload php file link and parameter "example.com/upload.php?image=\(imageData)"
request.httpMethod = "POST"
request.httpBody = param.data(using: String.Encoding.utf8)
let session = URLSession.shared
let task = session.dataTask(with: request as URLRequest) {data,response,error in
if error != nil {
print("error=\(error)")
return
}
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print(responseString!)
}
task.resume()
}
It won't work, how to send an image from an iOS Swift app to my PHP server?
#IBAction func upload(sender: UIButton) {
var imageData = UIImageJPEGRepresentation(img.image, 90)
// println(imageData)
let url = NSURL(string:"http://www.i35.club.tw/old_tree/test/uplo.php")
//let cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalCacheData
//var request = NSMutableURLRequest(URL: url, cachePolicy: cachePolicy, timeoutInterval: 10)
var request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
// set Content-Type in HTTP header
let boundaryConstant = "----------V2ymHFg03esomerandomstuffhbqgZCaKO6jy";
let contentType = "multipart/form-data; boundary=" + boundaryConstant
NSURLProtocol.setProperty(contentType, forKey: "Content-Type", inRequest: request)
request.HTTPBody = imageData
// set data
//var dataString = "adkjlkajfdadf"
//let requestBodyData = (dataString as NSString).dataUsingEncoding(NSUTF8StringEncoding)
//request.HTTPBody = requestBodyData
//
request.addValue(contentType, forHTTPHeaderField: "Content-Type")
request.addValue("multipart/form-data", forHTTPHeaderField: "Accept")
//
// set content length
//NSURLProtocol.setProperty(requestBodyData.length, forKey: "Content-Length", inRequest: request)
var response: NSURLResponse? = nil
var error: NSError? = nil
let reply = NSURLConnection.sendSynchronousRequest(request, returningResponse:&response, error:&error)
let results = NSString(data:reply!, encoding:NSUTF8StringEncoding)
println("API Response: \(results)")
}
//take photo
func imagePickerController(picker: UIImagePickerController!, didFinishPickingImage image: UIImage!, editingInfo: NSDictionary!) {
var selectedImage : UIImage = image
img.image = selectedImage
UIImageWriteToSavedPhotosAlbum(selectedImage, nil, nil, nil)
self.dismissViewControllerAnimated(true, completion: nil)
}
I have taken the photo by user's choice and written code for swift 2 and iOS9
func imageUploadRequest(imageView imageView: UIImageView, uploadUrl: NSURL, param: [String:String]?) {
//let myUrl = NSURL(string: "http://192.168.1.103/upload.photo/index.php");
let request = NSMutableURLRequest(URL:uploadUrl);
request.HTTPMethod = "POST"
let boundary = generateBoundaryString()
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let imageData = UIImageJPEGRepresentation(imageView.image!, 1)
if(imageData==nil) { return; }
request.HTTPBody = createBodyWithParameters(param, filePathKey: "file", imageDataKey: imageData!, boundary: boundary)
//myActivityIndicator.startAnimating();
let task = NSURLSession.sharedSession().dataTaskWithRequest(request,
completionHandler: {
(data, response, error) -> Void in
if let data = data {
// You can print out response object
print("******* response = \(response)")
print(data.length)
// you can use data here
// Print out reponse body
let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
print("****** response data = \(responseString!)")
let json = try!NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers) as? NSDictionary
print("json value \(json)")
//var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableContainers, error: &err)
dispatch_async(dispatch_get_main_queue(),{
//self.myActivityIndicator.stopAnimating()
//self.imageView.image = nil;
});
} else if let error = error {
print(error.description)
}
})
task.resume()
}
func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, imageDataKey: NSData, boundary: String) -> NSData {
let body = NSMutableData();
if parameters != nil {
for (key, value) in parameters! {
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.appendString("\(value)\r\n")
}
}
let filename = "user-profile.jpg"
let mimetype = "image/jpg"
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
body.appendString("Content-Type: \(mimetype)\r\n\r\n")
body.appendData(imageDataKey)
body.appendString("\r\n")
body.appendString("--\(boundary)--\r\n")
return body
}
func generateBoundaryString() -> String {
return "Boundary-\(NSUUID().UUIDString)"
}
}// extension for impage uploading
extension NSMutableData {
func appendString(string: String) {
let data = string.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
appendData(data!)
}
}
--------- following code for the php side
<?php
$firstName = $_POST["firstName"];
$lastName = $_POST["lastName"];
$userId = $_POST["userId"];
$target_dir = "media";
if(!file_exists($target_dir))
{
mkdir($target_dir, 0777, true);
}
$target_dir = $target_dir . "/" . basename($_FILES["file"]["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",
"userId" => $_REQUEST["userId"]
]);
} else {
echo json_encode([
"Message" => "Sorry, there was an error uploading your file.",
"Status" => "Error",
"userId" => $_REQUEST["userId"]
]);
}
To upload image with parameters use this code,
// Your method to upload image with parameters to server.
func uploadImageOne(){
var imageData = UIImagePNGRepresentation(imageView.image)
if imageData != nil{
var request = NSMutableURLRequest(URL: NSURL(string:"Enter 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)")
}
}
My updated code for Swift 3
func uploadImage() {
let url = URL(string: "YOUR SERVER URL");
let request = NSMutableURLRequest(url: url!);
request.httpMethod = "POST"
let boundary = "Boundary-\(NSUUID().uuidString)"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
var retreivedImage: UIImage? = nil
//Get image
do {
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as String
let readData = try Data(contentsOf: URL(string: "file://\(documentsPath)/myImage")!)
retreivedImage = UIImage(data: readData)
addProfilePicView.setImage(retreivedImage, for: .normal)
}
catch {
print("Error while opening image")
return
}
let imageData = UIImageJPEGRepresentation(retreivedImage!, 1)
if (imageData == nil) {
print("UIImageJPEGRepresentation return nil")
return
}
let body = NSMutableData()
body.append(NSString(format: "\r\n--%#\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format: "Content-Disposition: form-data; name=\"api_token\"\r\n\r\n" as NSString).data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format: (UserDefaults.standard.string(forKey: "api_token")! as NSString)).data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format: "\r\n--%#\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format:"Content-Disposition: form-data; name=\"profile_img\"; filename=\"testfromios.jpg\"\r\n").data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format: "Content-Type: application/octet-stream\r\n\r\n").data(using: String.Encoding.utf8.rawValue)!)
body.append(imageData!)
body.append(NSString(format: "\r\n--%#\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
request.httpBody = body as Data
let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: {
(data, response, error) -> Void in
if let data = data {
// do what you want in success case
} else if let error = error {
print(error.localizedDescription)
}
})
task.resume()
}
And PHP side code you can take from #VinodJoshi answer.
According to the blogpost of Sergey Kargopolov (http://swiftdeveloperblog.com/image-upload-example/) and his video (https://youtu.be/HqxeyS961Uk) here is my code that worked perfectly in Swift 5.
It will upload a picture to the directory specified in the php script (further down) and it will name the picture according to the imgKey given. In my example, it will upload the imageToUpload of myImageUploadRequest to the directory "wp-content/Images". The param dictionary is not necessarily needed. This could very well be written more efficiently but maybe it is a start for someone :)
func myImageUploadRequest(imageToUpload: UIImage, imgKey: String) {
let myUrl = NSURL(string: "https://yourdomain/uploadPicture.php");
let request = NSMutableURLRequest(url:myUrl! as URL);
request.httpMethod = "POST";
let param = [
"firstName" : "name",
"lastName" : "name",
"userId" : "42"
]
let boundary = generateBoundaryString()
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let imageData = imageToUpload.jpegData(compressionQuality: 1)
if imageData == nil {
return
}
request.httpBody = createBodyWithParameters(parameters: param, filePathKey: "file", imageDataKey: imageData! as NSData, boundary: boundary, imgKey: imgKey) as Data
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
print("error=\(error!)")
return
}
//print response
//print("response = \(response!)")
// print reponse body
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("response data = \(responseString!)")
}
task.resume()
}
func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, imageDataKey: NSData, boundary: String, imgKey: String) -> NSData {
let body = NSMutableData();
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 filename = "\(imgKey).jpg"
let mimetype = "image/jpg"
body.appendString(string: "--\(boundary)\r\n")
body.appendString(string: "Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
body.appendString(string: "Content-Type: \(mimetype)\r\n\r\n")
body.append(imageDataKey as Data)
body.appendString(string: "\r\n")
body.appendString(string: "--\(boundary)--\r\n")
return body
}
func generateBoundaryString() -> String {
return "Boundary-\(NSUUID().uuidString)"
}
}
extension NSMutableData {
func appendString(string: String) {
let data = string.data(using: String.Encoding.utf8, allowLossyConversion: true)
append(data!)
}
}
The server sided php (PHP/7.3.18) code:
<?php
$firstName = $_POST["firstName"];
$lastName = $_POST["lastName"];
$userId = $_POST["userId"];
$target_dir = "wp-content/Images";
if (!file_exists($target_dir)) {
mkdir($target_dir, 0777, true);
}
$target_dir = $target_dir . "/" . basename($_FILES["file"]["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",
"userId" => $_REQUEST["userId"]
]);
}
else {
echo json_encode([
"Message" => "Sorry, there was an error uploading your file.",
"Status" => "Error",
"userId" => $_REQUEST["userId"]
]);
}
?>
Example console output:
response data = {
"Message":"The file 9B862D73-9F0B-4DD3-8FBB-452AEF2FE1CF.jpg has been uploaded.",
"Status":"OK",
"userId":"17"}
I have made function for Block method which is easy to use and this is class function so you can use anywhere in your project for example make
MVCServer.swift
NSObject class and
import Alamofire
and then write this function in this class
func postImageRequestWithURL(withUrl strURL: String,withParam postParam: Dictionary<String, Any>,withImages imageArray:NSMutableArray,completion:#escaping (_ isSuccess: Bool, _ response:NSDictionary) -> Void)
{
Alamofire.upload(multipartFormData: { (MultipartFormData) in
// Here is your Image Array
for (imageDic) in imageArray
{
let imageDic = imageDic as! NSDictionary
for (key,valus) in imageDic
{
MultipartFormData.append(valus as! Data, withName:key as! String,fileName: "file.jpg", mimeType: "image/jpg")
}
}
// Here is your Post paramaters
for (key, value) in postParam
{
MultipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
}, usingThreshold: UInt64.init(), to: strURL, method: .post) { (result) in
switch result {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (progress) in
print("Upload Progress: \(progress.fractionCompleted)")
})
upload.responseJSON { response in
if response.response?.statusCode == 200
{
let json = response.result.value as? NSDictionary
completion(true,json!);
}
else
{
completion(false,[:]);
}
}
case .failure(let encodingError):
print(encodingError)
completion(false,[:]);
}
}
}
Now Call this Function
var ImageArray : NSMutableArray!
// Here is your post parameter
var parameters: [String:Any] = ["user_master_id" : “56”,
"first_name": “Jignesh”,
"last_name" : “Mayani”,
"email": “TestEmail#gmail.com”]
// Here is your image is in DATA formate don’t send as UIImage formate
let ImageDic = ["profile_image" : imageData!]
// Here you can pass multiple image in array i am passing just one
ImageArray = NSMutableArray(array: [ImageDic as NSDictionary])
MVCServer().postImageRequestWithURL(withUrl: "write Your URL here", withParam: parameters, withImages: ImageArray) { (isSuccess, response) in
// Your Will Get Response here
}
I would recommend to take a look at: https://github.com/sraj/Swift-SRWebClient
Sample function that worked for me:
func uploadImage(image:UIImage) {
let imageData:NSData = UIImageJPEGRepresentation(image, 100)
SRWebClient.POST("http://www.example.com/upload/")
.data(imageData, fieldName:"photo", data: ["foo":"bar","baz":"qux"])
.send({(response:AnyObject!, status:Int) -> Void in
// process success response
},failure:{(error:NSError!) -> Void in
// process failure response
})
}
You’ll notice that the above code is a slightly adjusted version of the snippets on the Swift-SRWebClient Github page. I’ve replaced NSData.dataWithData with UIImageJPEGRepresentation as the former is deprecated.
Also, don’t forget to drag SRWebClient.swift into your project folder, otherwise this won’t work :)
#IBAction func upload(sender: UIButton) {
var imageData = UIImageJPEGRepresentation(img.image, 90)
var url = NSURL(string: "http://www.i35.club.tw/old_tree/test/uplo.php")
var request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
request.HTTPBody = NSData.dataWithData(UIImagePNGRepresentation(imageData))
var response: NSURLResponse? = nil
var error: NSError? = nil
let reply = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error)
let results = NSString(data: reply!, encoding: NSUTF8StringEncoding)
println("API Response: \(results)")
}
Refer this link
This is great, I've been trying to pass an image using REST for a while and coouldn't format it just right and kept getting timeout errors. Using createBodyWithParameters I was able to make it work.
Here's the Swift 3 version of the code:
func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, imageDataKey: UIImage, boundary: String) -> Data {
var body = Data();
if parameters != nil {
for (key, value) in parameters! {
body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: String.Encoding.utf8)!)
body.append("\(value)\r\n".data(using: String.Encoding.utf8)!)
}
}
let filename = "user-profile.jpg"
let mimetype = "image/jpg"
body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Type: \(mimetype)\r\n\r\n".data(using: String.Encoding.utf8)!)
body.append(UIImageJPEGRepresentation(imageDataKey, 1)!)
//body.appendData(imageDataKey)
body.append("\r\n".data(using: String.Encoding.utf8)!)
body.append("--\(boundary)--\r\n".data(using: String.Encoding.utf8)!)
return body
}
Just look on that simple explanation:
Form data and multipart uploads with URLRequest
Also, to keep code up to date you can replace NSMutableData on Data. So your final code will be looks like:
func createHttpBody(parameters: [String: String]? = nil, _ boundary: String, data: Data, mimeType: String, filename: String) -> Data {
var body = Data()
let boundaryPrefix = "--\(boundary)\r\n"
if let parameters = parameters {
for (key, value) in parameters {
body.append(boundaryPrefix)
body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
body.append("\(value)\r\n")
}
}
body.append(boundaryPrefix)
body.append("Content-Disposition: form-data; name=\"file\"; filename=\"\(filename)\"\r\n")
body.append("Content-Type: \(mimeType)\r\n\r\n")
body.append(data)
body.append("\r\n")
body.append("--".appending(boundary.appending("--")))
return body
}
And updated extension for Data to use append method:
extension Data {
mutating func append(_ string: String) {
if let data = string.data(using: .utf8) {
append(data)
}
}
}
Also you can check this video tutorial and check source code for that tutorial.
In swift 4.1 and Xcode 9.4.1
See my Code in this blog for Upload image to server in Swift
https://markingios.blogspot.com/2018/09/upload-image-to-server-in-swift.html
Call this function like : uploadImage()
func uploadImage(){
let imageData = UIImageJPEGRepresentation(yourImage!, 1.0)//Replace your image
if imageData != nil{
var request = URLRequest(url: NSURL(string:urlString)! as URL)//Send your URL here
print(request)
request.httpMethod = "POST"
let boundary = NSString(format: "---------------------------14737809831466499882746641449")
let contentType = NSString(format: "multipart/form-data; boundary=%#",boundary)
// println("Content Type \(contentType)")
request.addValue(contentType as String, forHTTPHeaderField: "Content-Type")
var body = Data()
body.append(NSString(format: "\r\n--%#\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format:"Content-Disposition: form-data;name=\"title\"\r\n\r\n").data
(using:String.Encoding.utf8.rawValue)!)
body.append("Hello".data(using: String.Encoding.utf8, allowLossyConversion: true)!)
body.append(NSString(format: "\r\n--%#\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
body.append(NSString(format:"Content-Disposition: form-data;name=\"uploaded_file\";filename=\"image.jpg\"\\r\n").data
(using:String.Encoding.utf8.rawValue)!) //Here replace your image name and file name
body.append(NSString(format: "Content-Type: image/jpeg\r\n\r\n").data(using: String.Encoding.utf8.rawValue)!)
body.append(imageData!)
body.append(NSString(format: "\r\n--%#\r\n", boundary).data(using: String.Encoding.utf8.rawValue)!)
request.httpBody = body
let task = URLSession.shared.dataTask(with: request) { data, response, error in guard let data = data, error == nil
else { // check for fundamental networking error
print("error=\(String(describing: error))")
SharedClass.sharedInstance.alert(view: self, message: "\(String(describing: error!.localizedDescription))")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode == 500 {
SharedClass.sharedInstance.alert(view: self, message: "Server Error")
} else if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(String(describing: response))")
}
//This can print your response in string formate
let responseString = String(data: data, encoding: .utf8)
// let dictionary = data
// print("dictionary = \(dictionary)")
print("responseString = \(String(describing: responseString!))")
do {
self.response3 = (try JSONSerialization.jsonObject(with: data, options: []) as? [String: AnyObject])!
print(self.response3)
if (((self.response3["Response"] as? [String : Any])?["status"]) as! String == "SUCCESS") {
let message = (self.response3["Response"] as? [String : Any])?["message"] as? String
SharedClass.sharedInstance.alert(view:self, message: message)
} else {
let message = (self.response3["Response"] as? [String : Any])?["message"] as? String
SharedClass.sharedInstance.alert(view:self, message: message)
}
} catch let error as NSError {
print(error)
print(error.localizedDescription)
}
}
task.resume()
}
}
request.httpMethod = "POST" is important for upload long string or blob
func imageUpload(imageData:String){
var request:NSMutableURLRequest!
let param:String = "image=\(imageData)" // image data should be here
request = NSMutableURLRequest(url: URL(string: "www.pickmyoffers.com")!)// use your upload php file link and parameter "example.com/upload.php?image=\(imageData)"
request.httpMethod = "POST"
request.httpBody = param.data(using: String.Encoding.utf8)
let session = URLSession.shared
let task = session.dataTask(with: request as URLRequest) {data,response,error in
if error != nil {
print("error=\(error)")
return
}
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print(responseString!)
}
task.resume()
}