I have been doing some task about sending a String array using multipart-formdata in Alamofire to an Laravel host.
My code like :
//End coding data.
let stringsData = NSMutableData()
for string in arrayFriend {
if let stringData = string.email.dataUsingEncoding(NSUTF8StringEncoding) {
stringsData.appendData(stringData)
}
}
//Upload by form data.
Alamofire.upload(.POST, HTDefines.WEBSERVICE.CREATE_NEW_EVENT, multipartFormData: { (multipartFormData) -> Void in
//FRIENDS
multipartFormData.appendBodyPart(data: stringsData, name: HTDefines.KEY.FRIENDS)
}) { (result) -> Void in
switch (result) {
case .Success(let upload, _, _):
upload.progress { bytesRead, totalBytesRead, totalBytesExpectedToRead in
progress(totalBytesRead: totalBytesRead, totalBytesExpectedToRead: totalBytesExpectedToRead)
}
upload.responseJSON { response in
switch response.result {
case .Success(let JSON):
}
case .Failure(let error):
}
}
case .Failure:
break
}
}
}
But my server has respond :
array_unique() expects parameter 1 to be array
Anyone can help me? Thank you so much.
Related
I uploaded an image using almofire and it is being uploaded to the correct path I require.
However, I need to get some of the responses that are in my PHP backend code into my swift such as the filepath.
An image to make my question more clear and precise about what I want to get from the .responseJSON
In the image below is my response from the PHP code, I want to get the value of the filepath in swift. How can I achieve that?
Here is my code:
PHP:
<?php
if (empty($_FILES["image"])) {
$response = array("error" => "nodata");
}
else {
$response['error'] = "NULL";
$filename = uniqid() . ".jpg";
if (move_uploaded_file($_FILES['image']['tmp_name'], "../propertyImages/" . $filename)) {
$response['status'] = "success";
$response['filepath'] = "https://example.com/WebService/propertyImages/" . $filename;
$response['filename'] = "".$_FILES["file"]["name"];
} else{
$response['status'] = "Failure";
$response['error'] = "".$_FILES["image"]["error"];
$response['name'] = "".$_FILES["image"]["name"];
$response['path'] = "".$_FILES["image"]["tmp_name"];
$response['type'] = "".$_FILES["image"]["type"];
$response['size'] = "".$_FILES["image"]["size"];
}
}
echo json_encode($response);
?>
Swift Code:
self.imageData = propImage.image!.jpegData(compressionQuality: 0.5)!
let headers: HTTPHeaders = [
"Content-type": "multipart/form-data"
]
AF.upload(
multipartFormData: { multipartFormData in
multipartFormData.append(self.imageData!, withName: "image" , fileName: "file.jpg", mimeType: "image/jpeg")
},
to:"https://example.com/WebService/api/uploadPropImage.php", method: .post , headers: headers)
.responseJSON { resp in
//let responseString: String = String(data: self.imageData!, encoding: .utf8)!
print(resp) //this prints all the responses from the PHP code, my problem is how do i get a specific response, such as the filepath only and so on?
}
EDIT:
I tried some of the solutions, this one seems to be the one that will work but still gives an error reading
"No exact matches in call to class method 'jsonObject'"
Updated code:
AF.upload(multipartFormData: { multipartFormData in multipartFormData.append(self.imageData!, withName: "image" , fileName: "file.jpg", mimeType: "image/jpeg")}, to:"https://example.com/WebService/api/uploadPropImage.php", method: .post , headers: headers).responseJSON {
result in
do{
if let jsonResults = try JSONSerialization.jsonObject(with: result, options: []) as? [String: Any] { //error in this line
let filePath = jsonResults["filepath"] as? String
}
}catch{
print("ERROR")
}
Then just decode your response:
if let jsonResults = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
let filePath = jsonResults["filepath"] as? String // here is your value
}
The value of the responseJSON block, is a Result. It's a basic concept used frequently, so you need to learn how do handle it. Common practice is then to use a switch.
let headers: HTTPHeaders = ["Content-type": "multipart/form-data"]
AF.upload(multipartFormData: { multipartFormData in
multipartFormData.append(self.imageData!, withName: "image" , fileName: "file.jpg", mimeType: "image/jpeg")
},
to:"https://example.com/WebService/api/uploadPropImage.php", method: .post , headers: headers)
.responseJSON { result in
switch result {
case .success(let json):
guard let dictionary = json as? [String: Any] else { print("Response JSON is not a dictionary"); return }
guard let filePath = json["filePath"] as? String else { print("filePath key is not present in "\(json)" or is not a String"); return }
print("Filepath: \(filePath)")
case .failure(let error):
print("Error: \(error)")
}
}
Now, it might be better to use a Codable struct to parse your response and call responseDecodable() instead of using responseJSON() which will use JSONSerialization, method which is by the way deprecated and will be removed in next Alamofire major release.
I am trying to create simple login and signup in swift with php mysql in backend. I was following "https://github.com/EMacco/ios-tutorials/tree/yummie-network-connection/Yummie" this project
I get the following error
The response is: {"data":[{"response":"Success","username":"Mohammad Tariq Shamim"}]} Error Response could not be decoded
I am getting response from the server but JSON is not getting decoded. Following is my code
enum Route {
static let baseurl = "http://arabscholar.net/android/"
case login
var description: String {
switch self {
case .login: return "login.php"
}
}
}
struct User: Decodable{ let username: String? let response: String? }
struct ApiResponse<T: Decodable>: Decodable {
let status: Int
let data: T?
let error: String?
}
AppError Swift file
enum AppError: LocalizedError {
case errorDecoding
case unknownError
case invalidUrl
case serverError(String)
var errorDescription: String? {
switch self {
case .errorDecoding:
return "Response could not be decoded"
case .unknownError:
return "Unknown error"
case .invalidUrl:
return "Url invalid"
case .serverError(let error):
return error
}
}
}
Main networking struct file
struct NetworkService {
static let shared = NetworkService()
private init() {}
func signin(username: String, password: String, completion: #escaping(Result<User, Error>) -> Void) {
let params = ["login": "user", "email": username, "password": password]
request(route: .login, method: .post, parameters: params, completion: completion)
}
private func request<T: Decodable>(route: Route, method: Method, parameters: [String: Any]? = nil, completion: #escaping(Result<T, Error>) -> Void) {
guard let request = createRequest(route: route, method: method, parameters: parameters) else {
completion(.failure(AppError.unknownError))
return
}
URLSession.shared.dataTask(with: request) { data, response, error in
var result: Result<Data, Error>?
if let data = data {
result = .success(data)
let responseString = String(data: data, encoding: .utf8) ?? "Could not stringify our data"
print("The response is: (responseString)")
} else if let error = error {
result = .failure(error)
print("The error is " + error.localizedDescription)
}
DispatchQueue.main.async {
self.handleResponse(result: result, completion: completion)
}
}.resume()
}
private func handleResponse<T: Decodable>(result: Result<Data, Error>?, completion: (Result<T, Error>) -> Void) {
guard let result = result else {
completion(.failure(AppError.unknownError))
return
}
switch result {
case .success(let data):
let decoder = JSONDecoder()
guard let response = try? decoder.decode(ApiResponse.self, from: data) else {
completion(.failure(AppError.errorDecoding))
return
}
if let error = response.error {
completion(.failure(AppError.serverError(error)))
return
}
if let decodedData = response.data {
completion(.success(decodedData))
} else {
completion(.failure(AppError.unknownError))
}
case .failure(let error):
completion(.failure(error))
}
}
private func createRequest(route: Route, method: Method, parameters: [String: Any]? = nil) -> URLRequest? {
let urlString = Route.baseurl + route.description
guard let url = urlString.asUrl else {return nil}
var urlRequest = URLRequest(url: url)
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.httpMethod = method.rawValue
if let params = parameters {
switch method {
case .get:
var urlComponent = URLComponents(string: urlString)
urlComponent?.queryItems = params.map { URLQueryItem(name: $0, value: "($1)")}
urlRequest.url = urlComponent?.url
case .post:
let bodyData = try?JSONSerialization.data(withJSONObject: params, options: [])
urlRequest.httpBody = bodyData
}
}
return urlRequest
}
}
My PHP code
$postdata = json_decode( file_get_contents( "php://input" ), TRUE );
//$id = $postdata[ "email" ];
//$name = $postdata[ "password" ];
$result[ 'response' ] = "Success";
$result[ 'username' ] = "Mohammad Tariq Shamim";
// Store values in an array
$returnValue = array( $result );
$array['data'] = $returnValue;
// Send back request in JSON format
echo json_encode( $array );
//echo json_encode( array( 'response' => 'No data found for ' . $_POST[ 'email' ] ) );
I am new to swift and tried many blog posts and github to take image from library and upload it to server(php server side). can you please write the code which takes photo from photo library and upload it to server using alamofire and any other method.
below is the code i was trying to upload photo from photolibrary
#IBAction func upload(_ sender: Any) {
let picker = UIImagePickerController()
picker.delegate = self
picker.sourceType = UIImagePickerControllerSourceType.photoLibrary
picker.allowsEditing = false
self.present(picker, animated: true) {
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let originalImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
imageView.image = originalImage
let image = UIImage.init(named: "\(originalImage)")
let imgData = UIImageJPEGRepresentation(image!, 0.2)!
let parameters = ["user":"Sol", "password":"secret1234"]
Alamofire.upload(multipartFormData: { multipartFormData in
multipartFormData.append(imgData, withName: "fileset",fileName: "file.jpg", mimeType: "image/jpg")
for (key, value) in parameters {
multipartFormData.append(value.data(using: String.Encoding.utf8)!, withName: key)
} //Optional for extra parameters
},
to:"website")
{ (result) in
switch result {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (progress) in
print("Upload Progress: \(progress.fractionCompleted)")
})
upload.responseJSON { response in
print(response.result.value)
}
case .failure(let encodingError):
print(encodingError)
}
}
}
self.dismiss(animated: true, completion: nil)
}
}
#IBAction func upload(_ sender: Any) {
let picker = UIImagePickerController()
picker.delegate = self
picker.sourceType = UIImagePickerControllerSourceType.photoLibrary
picker.allowsEditing = false
self.present(picker, animated: true) {
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let originalImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
imageView.image = originalImage
if let imgData = UIImageJPEGRepresentation(originalImage, 0.2) {
let parameters = ["user":"Sol", "password":"secret1234"]
upload(params: parameters, imageData: imgData)
}
}
picker.dismiss(animated: true, completion: nil)
}
func upload(params : [String: Any], imageData: Data) {
if let url = URL(string: "EnterUrl") {
Alamofire.upload(
multipartFormData: { (multipartdata) in
multipartdata.append(
imageData,
withName: "fileset",
fileName: String("\(Date().timeIntervalSince1970).jpg"),
mimeType: "image/jpg"
)
for (key,value) in params {
if let data = value as? String,
let data1 = data.data(using: .utf8)
{
multipartdata.append(
data1,
withName: key
)
}
}
},
to: url,
method: .post,
headers: nil,
encodingCompletion: { (result) in
switch result {
case .success(let upload, _, _):
upload.responseJSON(completionHandler: { (response) in
if let err = response.error {
print(err.localizedDescription)
} else {
print(response.result.value ?? "No data")
}
})
case .failure(let error):
print(error.localizedDescription)
}
}
)
}
}
}
try this.
I'm using this code (Swift) to upload an image that user selected from their photos to a server:
let imageFormatted = UIImageJPEGRepresentation(imageView.image!, 0.5);
let uuid = NSUUID().UUIDString
print ("MARK -- UUID is " + uuid)
Alamofire.upload(
.POST,
"http://www.memer.onlie/upload.php",
multipartFormData: { multipartFormData in
multipartFormData.appendBodyPart(data: imageFormatted!, name: "imagefile",
fileName: uuid + ".jpg", mimeType: "image/jpeg")
},
encodingCompletion: { encodingResult in
switch encodingResult {
case .Success(let upload, _, _):
upload.validate()
upload.responseJSON { response in
dispatch_async(dispatch_get_main_queue()) {
self.displayAlert("Uploaded!", message: "Your meme was uploaded, and you might see it in the app soon!", responseButtonText: "<3")
}
var json = JSON(data: response.data!)
print ("MARK -- JSON response: " + json["response"].stringValue)
}
print ("MARK -- Upload success!")
case .Failure(let encodingError):
print(encodingError)
print ("MARK -- Upload failure!")
self.displayAlert("Issue uploading.", message: "There was an issue uploading your meme.", responseButtonText: "Aww :(")
}
}
)
No image is being uploaded to the server. What can I correct to get this to work?
Edited code.
This thread helps you understand what you have not considered and what you need to do to solve the issue. I guess you need to set request header and body part properly. If you use Alamofire and have to use 'multipart/form-data' encoding type, you can write code like this.
Alamofire.upload(.POST, destURL, headers: yourHeader, multipartFormData: { multipartFormData in
if let imageData = UIImageJPEGRepresentation(image, 0.5) {
multipartFormData.appendBodyPart(data: imageData, name:"file", fileName: "imagefile", mimeType: "image/jpg")
}
// Append parameters you should send
for (key, value) in parameters {
multipartFormData.appendBodyPart(data: value.dataUsingEncoding(NSUTF8StringEncoding)!, name: key)
}
}, encodingCompletion: { encodingResult in
switch encodingResult {
case .Success(let upload, _, _):
upload.validate()
upload.responseJSON { response in
// do something if response is success
}
case .Failure(_):
// do something if response is fail
}
})
I'm trying to upload UIImage to a server via a web api. I'm creating my web rest API with laravel 5.2.
Here is my function in Swift which should make a post request to my API with the UIImage and some parameters:
func uploadWithAlamofire(imageUpload: UIImage) {
let image = imageUpload
// define parameters
let parameters = [
"hometown": "abc",
"living": "abc"
]
// Begin upload
Alamofire.upload(.POST, "http://localhost:8888/buyIT/public/app/api/createPost",
// define your headers here
headers: ["Authorization": "auth_token"],
multipartFormData: { multipartFormData in
// import image to request
if let imageData = UIImageJPEGRepresentation(image, 1) {
multipartFormData.appendBodyPart(data: imageData, name: "file", fileName: "myImage.png", mimeType: "image/png")
}
// import parameters
for (key, value) in parameters {
multipartFormData.appendBodyPart(data: value.dataUsingEncoding(NSUTF8StringEncoding)!, name: key)
}
},
// you can customise Threshold if you wish. This is the alamofire's default value
encodingMemoryThreshold: Manager.MultipartFormDataEncodingMemoryThreshold,
encodingCompletion: { encodingResult in
switch encodingResult {
case .Success(let upload, _, _):
upload.responseJSON { response in
print(response)
}
case .Failure(let encodingError):
print(encodingError)
}
})
}
But I don't know how to get the image and then upload it to my server.
Here is what I tried in my web api:
public function createPost(Request $request)
{
$file = $request->input('file');
$input = $request->only('hometown');
//Create deals folder if not exist
if (!file_exists('Upload/images')) {
mkdir('Upload/images', 0777, true);
}
if(file_exists('Upload/images'))
{
// SET UPLOAD PATH
$destinationPath = 'Upload/images';
// GET THE FILE EXTENSION
if ($file != null) {
$extension = $file->getClientOriginalExtension();
// RENAME THE UPLOAD WITH RANDOM NUMBER
$fileName = rand(11111, 99999) . '.' . $extension;
// MOVE THE UPLOADED FILES TO THE DESTINATION DIRECTORY
$upload_success = $file->move($destinationPath, $fileName);
//$filePath = url('/').'/'.$destinationPath.'/'.$fileName;
if($upload_success)
{
return "success";
}
else {
return "failed !!!";
}
}
}
else
{
return "failed";
}
return $file;
}
Or , You can use AlamoFire
func createMultipart(image: UIImage, callback: Bool -> Void){
// use SwiftyJSON to convert a dictionary to JSON
var parameterJSON = JSON([
"id_user": "test"
])
// JSON stringify
let parameterString = parameterJSON.rawString(encoding: NSUTF8StringEncoding, options: nil)
let jsonParameterData = parameterString!.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
// convert image to binary
let imageData = UIImageJPEGRepresentation(image, 0.7)
// upload is part of AlamoFire
upload(
.POST,
URLString: "http://httpbin.org/post",
multipartFormData: { multipartFormData in
// fileData: puts it in "files"
multipartFormData.appendBodyPart(fileData: jsonParameterData!, name: "goesIntoFile", fileName: "json.txt", mimeType: "application/json")
multipartFormData.appendBodyPart(fileData: imageData, name: "file", fileName: "iosFile.jpg", mimeType: "image/jpg")
// data: puts it in "form"
multipartFormData.appendBodyPart(data: jsonParameterData!, name: "goesIntoForm")
},
encodingCompletion: { encodingResult in
switch encodingResult {
case .Success(let upload, _, _):
upload.responseJSON { request, response, data, error in
let json = JSON(data!)
println("json:: \(json)")
callback(true)
}
case .Failure(let encodingError):
callback(false)
}
}
)
}
let fotoImage = UIImage(named: "foto")
createMultipart(fotoImage!, callback: { success in
if success { }
})