I have a problem uploading a Document file through Document picker controller. I have selected File through Document picker. and send file using multipart data in service. but xcode give some error in ios swift.
Here is my code For Image upload.
Alamofire.upload(multipartFormData: { (multipartFormData) in
for (key, value) in params {
multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
multipartFormData.append(imageData!, withName: "upload_photo", fileName: "img.png", mimeType: "image/jpeg")
}, to:pageURL)
{ (result) in
switch result {
case .success(let upload, _, _):
self.stopLoader()
upload.uploadProgress(closure: { (Progress) in
print("Upload Progress: \(Progress.fractionCompleted)")
})
But i have to upload Document file from url.
Use my below class it is simple and manageable and working file :
import UIKit
import Alamofire
class TDWebServices: NSObject {
static let shared = TDWebServices()
func post(urlString : String , param : [String : Any], completionHandler : #escaping ( _ result : Any?) -> ()) {
Alamofire.request(urlString, method: .post, parameters: param, encoding: JSONEncoding.default, headers: ["Accept": "application/json"]).responseJSON { (response) in
switch response.result {
case .success:
let json = response.result.value as? NSDictionary
completionHandler(json)
case .failure(let error):
print(error)
completionHandler(nil)
return
}
}
}
func uploadImage(urlString : String , image : UIImage, param : [String : Any], completionHandler : #escaping ( _ result : Any?) -> ()) {
guard let imageData = UIImageJPEGRepresentation(image, 0.5) else {
print("Could not get JPEG representation of UIImage")
return
}
let header: HTTPHeaders = [
"Content-type": "multipart/form-data"
]
Alamofire.upload(multipartFormData: { multipartFormData in
for (key, value) in param {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
}
multipartFormData.append(imageData,
withName: "image", // <- It is param for uploading the file make sure it is perfect as per your API
fileName: "image.jpg",
mimeType: "image/jpeg")
},
to: urlString,
headers: header, // ["Authorization": "Basic xxx"]
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.uploadProgress { progress in
// progressCompletion(Float(progress.fractionCompleted))
}
upload.validate()
upload.responseJSON { response in
completionHandler(response.result.value)
}
case .failure(let encodingError):
print(encodingError)
completionHandler(nil)
}
})
}
}
How to use?
let param = ["user_id" : 123 as Any] // Whatever your params are
// showActivity() // <- show activity indicator
TDWebServices.shared.post(urlString: <your_api_url>, param: param) { (res) in
// hideActivity() // <- hide activity indicator
if res != nil{
let aDict = res as? [String : Any] // your response
// Hnadle your code here
}
else{
self.showAlert(title: "Invalid!", message: "Internet connection issue.", calcelHandler: {}) // <- If you have internet issue
}
}
Still facing issue then let me know..
Related
I'm currently working on iOS applications and I'm using multipart image upload to uploading images to the server. Following is my image uploading method.
func uploadImageData(imageType:Int, uploadId:String, fileName:String, imageFile:UIImage, completion:#escaping (APIResponseStatus, ImageUploadResponse?) -> Void) {
let image = imageFile
let imgData = image.jpegData(compressionQuality: 0.2)!
let params = [APIRequestKeys.imageType:imageType, APIRequestKeys.uploadId:uploadId, APIRequestKeys.fileName:fileName] as [String : Any]
//withName is the post request key for the image file
Alamofire.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append(imgData, withName: APIRequestKeys.imageFile, fileName: "\(fileName).jpg", mimeType: "image/jpg")
for (key, value) in params {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key)
}
}, to: Constants.baseUrl + APIRequestMetod.uploadImageData, headers:self.getImageUploadHeaders())
{ (result) in
switch result {
case .success(let upload, _, _):
APIClient.currentRequest = upload
upload.uploadProgress(closure: { (progress) in
})
upload.responseObject {
(response:DataResponse<ImageUploadResponse>) in
switch response.result {
case .success(_):
completion(APIClient.APIResponseStatus(rawValue: (response.response?.statusCode)!)!, response.value!)
case .failure(let encodingError):
if let err = encodingError as? URLError, err.code == .notConnectedToInternet {
completion(APIClient.APIResponseStatus.NoNetwork, nil)
} else {
completion(APIClient.APIResponseStatus.Other, nil)
}
}
}
case .failure( _):
completion(APIClient.APIResponseStatus.Other, nil)
}
}
}
But for this implementation server is always sending exif data error. Following is the error that I'm getting.
exif_read_data(A029C715-99E4-44BE-8691-AA4009C1F5BD_FOTOPREGUNTA.ico): Illegal IFD size in
upload_image_xhr.php on line
The important thing is this service is working without errors in POSTMAN and android application as well. This error is only getting for my iOS implementation. My backend developer telling me that there is and exif data error in data that I'm sending and please verify the data from my side.
Anyone have an idea about this?
Thanks in advance.
I will make block function for Upload image to Server Using Multipart
//Here strUrl = YOUR WEBSERVICE URL
//postParam = post Request parameter i.e.
//let postParam : [String : Any] = [first_name : "name"]
//imageArray = image upload array i.e.
//var imageArray : [[String:Data]] = [["image_name" : YOUR IMAGE DATA]]
func postImageRequestWithURL(withUrl strURL: String,withParam postParam: Dictionary<String, Any>,withImages imageArray:[[String:Data]], completion:#escaping (_ isSuccess: Bool, _ response:NSDictionary) -> Void)
{
let requetURL = strURL
Alamofire.upload(multipartFormData: { (MultipartFormData) in
for (imageDic) in imageArray
{
for (key,valus) in imageDic
{
MultipartFormData.append(valus, withName:key,fileName: "file.jpg", mimeType: "image/jpg")
}
}
for (key, value) in postParam
{
MultipartFormData.append("\(value)".data(using: .utf8)!, withName: key)
// MultipartFormData.append(value, withName: key)
}
}, usingThreshold: UInt64.init(), to: requetURL, method: .post, headers: ["Accept": "application/json"]) { (result) in
switch result {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (progress) in
print("Upload Progress: \(progress.fractionCompleted)")
})
upload.responseJSON { response in
let desiredString = NSString(data: response.data!, encoding: String.Encoding.utf8.rawValue)
print("Response ====================")
print(desiredString!)
if let json = response.result.value as? NSDictionary
{
if response.response?.statusCode == 200
|| response.response?.statusCode == 201
|| response.response?.statusCode == 202
{
completion(true,json);
}
else
{
completion(false,json);
}
}
else
{
completion(false,[:]);
}
}
case .failure(let encodingError):
print(encodingError)
completion(false,[:]);
}
}
}
I Hope this will help...
I want to send this data in the form of multipart to server with image/video. I have image/video data in byte data form (NSData or Data)
{"mediauploadata":
{
"type":"poll",
"server_token":"03f0e635b4c01b9f398de393259de8650b54c85c24f49998af50593643f559230d95e8e605612653769f4871b543e25d48bf",
"id":"105"
}
}
I have created a function for Multipart Upload using Alamofire.
Call this function passing Web service URL , Parameters and your image.
func WSPostAPIMultiPart(_ aStrULR:String,
param: [String: Any],
image : UIImage?,
controller: UIViewController,
successBlock: #escaping (_ response:[String : Any]?) -> Void,
failureBlock: #escaping (_ error: Error?) -> Void) {
var dictHeaders : HTTPHeaders = [String : String]()
if (Alamofire.NetworkReachabilityManager()?.isReachable)!{
Alamofire.upload(
multipartFormData: { MultipartFormData in
let JSONData: Data? = try? JSONSerialization.data(withJSONObject: param, options: .prettyPrinted)
MultipartFormData.append(JSONData!, withName: "json")
if image != nil{
MultipartFormData.append(UIImageJPEGRepresentation(image!, 0.5)!, withName: "profile_image",fileName: "image.jpeg", mimeType: "image/jpeg")
// withName : You will pass the key name required by your server
}
}, to: aStrULR ,method : .post , headers : dictHeaders) { (result) in
switch result {
case .success(let upload, _, _):
upload.responseJSON { response in
if let value = response.result.value {
let dictResponse = JSON(value).dictionaryObject
successBlock(dictResponse)
}
}
case .failure(let error):
failureBlock(error)
}
}
}else{
print("NO INTERNET CONNECTIVITY")
}
}
For Video: Just pass videoURL one extra parameter and append as :
MultipartFormData.append(videoUrl, withName: "profileVideo", fileName: "video.mp4", mimeType: "video/mp4")
Hope it helps :)
func uploadDataWith(parameter params:Dictionary<String,String>,data:Data?,isImage:Bool,handler:#escaping ((Dictionary<String,Any>?) -> Void)) {
Alamofire.upload(multipartFormData: { (multipartFormData) in
for (key, value) in params {
multipartFormData.append(value.data(using: String.Encoding.utf8, allowLossyConversion: false)!, withName: key)
}
if data != nil && isImage {
multipartFormData.append(data, withName: "photo_upload", fileName: "file.png", mimeType: "image/png")
}
if data != nil && !isImage {
multipartFormData.append(data, withName: "video_upload", fileName: "file.mp4", mimeType: "video/mp4")
}
}, to: "http://") { (encodingResult) in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
switch response.result {
case .success:
if let jsonDict = response.result.value as? Dictionary<String,Any> {
print("Json Response: \(jsonDict)")
handler(jsonDict)
print(jsonDict,(response.response!.statusCode))
}
else{
print(response.response!.statusCode)
handler(nil)
}
if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {
print("Server Response: \(utf8Text)") // original server data as UTF8 string
}
break
case .failure(let error):
print(response.response!.statusCode)
print_debug(error)
handler(nil)
break
}
}
case .failure(let encodingError):
print(encodingError)
}
}
}
I am trying to upload image but need to pass parameters and header as well, got help from google about parameters but not getting how to pass header also. Passing on the code below please guide.
Below is my code:
if (request.requestType == "Multipart")
{
var strToken : String = ""
if let access_token = UserDefaults.standard.string(forKey: "auth_token"){
let tokenValue = String(format: "Token %#", access_token);
strToken = tokenValue
}
let headers: HTTPHeaders = [
"Authorization": strToken,
"Content-Type": "multipart/form-data"
]
let img = request.image
let imgData = UIImageJPEGRepresentation(img, 0.2)!
do{
let strURL = try strCompleteURL.asURL()
Alamofire.upload(multipartFormData: { multipartFormData in
multipartFormData.append(imgData, withName: "image_path",fileName: "file.jpg", mimeType: "image/jpg")
for (key, value) in params {
multipartFormData.append(value.data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
},
to:strURL)
{ (result) in
switch result {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (progress) in
print("Upload Progress: \(progress.fractionCompleted)")
})
upload.responseJSON { response in
if response.result.isSuccess {
print(response.result.value as Any)
if let data = response.data{
self.response.responseCode = response.response?.statusCode
self.processResult(data);
}
}
}
case .failure(let encodingError):
print(encodingError)
}
}
}
catch{
}
above code tries to upload image but not succeed because of missing header, please guide how to pass header and parameters as well.
Thanks
Hi I have used headers like this
func uploadImage( image:UIImage, url:String, _ successBlock:#escaping ( _ response: JSON )->Void , errorBlock: #escaping (_ error: NSError) -> Void ){
let path = baseUrl + url
print(path)
let headers = ["authorization": AppData().token]
let imgData = UIImageJPEGRepresentation(image, 0.2)!
let URL = try! URLRequest(url: path, method: .post, headers: headers)
Alamofire.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append(imgData, withName: "image",fileName: "file.jpg", mimeType: "file")
for (key, value) in params {
multipartFormData.append(value.data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
}, with: URL) { (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)
if let value = response.result.value {
let json = JSON(value)
successBlock(json)
}
}
case .failure(let encodingError):
print(encodingError)
errorBlock(encodingError as NSError)
}
}
}
The Alamofire .upload() function has more parameters available than what you used. (This can be seen in the Alamofire.swift file in their pod folder)
public func upload(
multipartFormData: #escaping (MultipartFormData) -> Void,
usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold,
to url: URLConvertible,
method: HTTPMethod = .post,
headers: HTTPHeaders? = nil,
encodingCompletion: ((SessionManager.MultipartFormDataEncodingResult) -> Void)?)
{
return ...
}
In there you can see there is a parameter for headers that you have not made use of.
Without running the code myself and checking everything, this would be my best assumption of where your headers would go
I need to call the Multipart request with Image file and JSON.
I have tried this, but still getting the error.
// define parameters
let parameters = [
"hometown": "yalikavak",
"living": "istanbul"
]
Alamofire.upload(multipartFormData: { multipartFormData in
if let imageData = UIImageJPEGRepresentation(image, 1) {
multipartFormData.append(imageData, withName: "file", fileName: "file.png", mimeType: "image/png")
}
for (key, value) in parameters {
multipartFormData.append((value?.data(using: .utf8))!, withName: key)
}}, to: "upload_url", method: .post, headers: ["Authorization": "auth_token"],
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.response { [weak self] response in
guard let strongSelf = self else {
return
}
debugPrint(response)
}
case .failure(let encodingError):
print("error:\(encodingError)")
}
})
}
How to send the JSON?
Try This Code for Multiple upload Images in Single Request, This code is already working.
// For Pass Valid Parameters & number of Images in Array in Image Upload Function
var dicImgData : NSMutableDictionary? = NSMutableDictionary()
if let img = UIImage(named: "Your Image") {
if let data:Data = UIImagePNGRepresentation(img) {
var imageData : NSData = data
dicImgData! .setObject(imageData, forKey: "data" as NSCopying)
dicImgData! .setObject("file", forKey: "name" as NSCopying)
dicImgData! .setObject("file.png", forKey: "fileName" as NSCopying)
dicImgData! .setObject("image/png", forKey: "type" as NSCopying)
let dicParameter = [
"hometown": "yalikavak",
"living": "istanbul"
]
self.uploadImage(url: "Your URL", Parameter: dicParameter, Images: [dicImgData])
}
}
Upload Function
func uploadImage (url: String, Parameter param : NSDictionary, Images arrImage: NSArray) -> Void
{
var requestURL : String! = url
let headers = [
"Authorization": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==",
"Accept": "application/json",
]
print("---------------------")
print("Request URL :- \(requestURL)")
print("---------------------")
Alamofire.upload(multipartFormData: { (data) in
for (key, value) in param {
data.append((value as! String).data(using: .utf8)!, withName: key as! String)
}
for imageInfo in arrImage
{
var dicInfo : NSDictionary! = imageInfo as! NSDictionary
data.append(dicInfo["data"] as! Data, withName: dicInfo["name"] as! String, fileName: dicInfo["fileName"] as! String, mimeType: dicInfo["type"] as! String)
dicInfo = nil
}
}, to: requestURL, method: .post , headers:nil, encodingCompletion: { (encodeResult) in
switch encodeResult {
case .success(let upload, _, _):
upload.responseJSON(completionHandler: { (response) in
switch response.result
{
case .success(let responseJSON):
guard let dicResponse = responseJSON as? NSDictionary else{
return
}
print("Response : \((dicResponse))")
case .failure(let error):
print(error)
break
}
})
case .failure(let error):
print(error)
break
}
})
}
From data you have given, I comes to an conclusion as given below.
The status code 400 means json you're passing to the api was not following the api documentation. For example if they expect a key "name" and you're not given such a key at all.
Other possible reasons for this error.
Seems like you haven't mentioned any of content types
Add these line of code to assure that the response and your request are in proper formats
Alamofire.request(.GET, "your url", parameters: ["foo": "bar"])
.validate(statusCode: 200..<300)
.validate(contentType: ["application/json"])
.response { (_, _, _, error) in
println(error)
}
The Accept header tells the server what your client wants in the
response. The Content-Type header tells the server what the client
sends in the request.
If you can give more information we can help further.
Here I made my custom webservice, You can use it. This webservice is for upload dictionary with image and video or both or without it.
import Foundation
import Alamofire
class WebServiceHandler: AnyObject {
func uploadWithAlamofire(Parameters params : [NSObject : AnyObject]?,ImageParameters imgparams : [NSObject : AnyObject]?,VideoParameters vidoparam : [NSObject : AnyObject]?,Action action : NSString, success: #escaping (AnyObject) -> Void, failure: #escaping (AnyObject) -> Void)
{
var base_url = "http://benzatineinfotech.com/webservice/finder/index.php/Web_api/"
base_url.append(action as String)
Alamofire.upload(multipartFormData: { multipartFormData in
if imgparams != nil{
for (key, value) in imgparams! {
if let imageData = UIImageJPEGRepresentation(value as! UIImage, 1) {
multipartFormData.append(imageData, withName: key as! String, fileName: "\(NSDate().timeIntervalSince1970 * 1000)).jpg", mimeType: "image/jpg")
}
}
}
if vidoparam != nil{
for (key, value) in vidoparam! {
multipartFormData.append(value as! URL , withName: key as! String, fileName: "\(NSDate().timeIntervalSince1970 * 1000).mp4", mimeType: "application/octet-stream")
}
}
if params != nil
{
for (key, value) in params! {
multipartFormData.append((value as! String).data(using: .utf8)!, withName: key as! String)
}
} }, to: base_url, method: .post, headers: nil,
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.uploadProgress { progress in
print(progress.fractionCompleted)
}
upload.response { [weak self] response in
guard self != nil else {
return
}
let responseString = String(data: response.data!, encoding: String.Encoding.utf8)
return success(responseString as AnyObject)
}
case .failure(let encodingError):
print("error:\(encodingError)")
return failure(encodingError as AnyObject)
}
})
}
func convertToDictionary(text: String) -> [String: Any]? {
if let data = text.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
} catch {
print(error.localizedDescription)
}
}
return nil
}
}
Usage:
self.webservice.uploadWithAlamofire(Parameters: dict_params as [NSObject : AnyObject], ImageParameters: imgparam as [NSObject : AnyObject], VideoParameters: videoparam as [NSObject : AnyObject], Action: "write_message", success: { (success) in
print(success)
}) { (error) in
print(error)
}
I am using this function to upload multiple images with parameters in post method in Alamofire. My image is not uploading. I cross checked there is no entry of image on server but other data successfully stored in DB .
I was using this method in Alamofire 3.0 and now I updated to 4.0 . Other post and get function are working fine for me.
static func callUploadApi (_ url: String , parameter:[String: String] , images: [URL] , imageParameterName:String ,showHud:Bool , handler: #escaping (_ result : NSMutableDictionary) -> Void )
{
Alamofire.upload(multipartFormData: { multipartFormData in
for (key, value) in parameter // Add Paramters
{
multipartFormData.append(value.data(using: .utf8 )! , withName: key)
}
for imageUrl in images // Add Images
{
multipartFormData.append(imageUrl, withName: imageParameterName)
}
}, to: "\(baseUrl)\(url)", method: .post,
encodingCompletion: { encodingResult in
switch encodingResult {
case .success(let upload, _, _):
print(upload.progress)
upload.responseJSON { response in
if let JSON = response.result.value
{
print("***********************************************")
print("JSON: \(JSON)")
print("***********************************************")
handler(JSON as! NSMutableDictionary)
}
}
break
case .failure(let encodingError):
print("error:\(encodingError)")
}
})
}
func urlRequestWithComponents(urlString:String, parameters:Dictionary<String, String>, imageData:NSData) -> (URLRequestConvertible, NSData) {
let mutableURLRequest = NSMutableURLRequest(URL: NSURL(string: urlString)!)
mutableURLRequest.HTTPMethod = Alamofire.Method.POST.rawValue
let boundaryConstant = "------------0x0x0x0x0x0x0x0x";
let contentType = NSString(format: "multipart/form-data;boundary=%#",boundaryConstant)
mutableURLRequest.setValue(contentType as String, forHTTPHeaderField: "Content-Type")
let uploadData = NSMutableData()
uploadData.appendData("\r\n--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
uploadData.appendData(NSString(format: "Content-Disposition: form-data; name=\"file\";filename=\"%#\"\r\n", self.imageURL).dataUsingEncoding(NSUTF8StringEncoding)!)
uploadData.appendData("Content-Type: application/octet-stream\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
uploadData.appendData(imageData)
for (key, value) in parameters {
uploadData.appendData("\r\n--\(boundaryConstant)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
uploadData.appendData("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n\(value)".dataUsingEncoding(NSUTF8StringEncoding)!)
}
uploadData.appendData("\r\n--\(boundaryConstant)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!)
return (Alamofire.ParameterEncoding.URL.encode(mutableURLRequest, parameters: nil).0, uploadData)
}
This worked for me, I write this for my need. Anyone can change it according to there need.
static func upload( _ url : String ,
parameter : [String : String] = [:],
arrayImage : [String : UIImage],
shouldShowHud : Bool = true,
completionHandler : #escaping (_ result : NSDictionary , _ status : Bool) -> Void )
{
Alamofire.upload(multipartFormData: { multipartFormData in
for (key, value) in parameter{
multipartFormData.append(value.data(using: .utf8 )! , withName: key)
}
for (key, value) in arrayImage {
if let imageData = UIImageJPEGRepresentation(imageUrl, 0.5) {
multipartFormData.append(imageData , withName: key, fileName: "file.jpeg", mimeType: "image/jpeg")
}
}
}, to: MainUrl+url , method: .post, headers : Header, encodingCompletion: { encodingResult in
switch encodingResult{
case .success(let upload, _, _):
print("Upload Progress \(upload.uploadProgress.completedUnitCount) '\' \(upload.uploadProgress.totalUnitCount)")
upload.responseJSON { response in
if let JSON = response.result.value {
let status = (JSON as! NSDictionary)["status"] as? Bool
completionHandler(JSON as! NSDictionary , status!)
} else {
let result : NSDictionary = ["message" : "Request Time out, please refresh again." as Any]
completionHandler( result as NSDictionary , false)
}
}
break
case .failure:
let result : NSDictionary = ["message" : "Request Time out, please refresh again." ]
completionHandler( result as NSDictionary , false)
break
}
}
)
}