Alamofire uploading progress - ios

I need to send a file with the parameters and tracking the progress of uploading. Method
Alamofire.request(.POST, "http://httpbin.org/post", parameters: parameters, encoding: .JSON)
don't track progress uploading. Method
Alamofire.upload(.POST, "http://httpbin.org/post", file: fileURL)
.progress { (bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) in
println(totalBytesWritten)
}
.responseJSON { (request, response, JSON, error) in
println(JSON)
}
is not able to set the parameters
is it possible to send a file with the parameters and tracking the progress of uploading?

You have to use .uploadProgress instead of .progress.

Use this way
activeVidoeCell.uploadRequest = Alamofire.upload(fileData as Data, to: url, method: .put, headers: nil).uploadProgress(closure: { (progress) in
print(progress.fractionCompleted)
activeVidoeCell.downloadButton.setProgress(CGFloat(progress.fractionCompleted), animated: true)
}).responseJSON(completionHandler: { (result) in
completionHandler(result)
})

Related

when i am trying to print a json result using alamofire with swift 4 i am getting an "Error Domain=kCFErrorDomainCFNetwork Code=303"

Alamofire.request("https://www.googleapis.com/youtube/v3/playlists",
method: .get, parameters: ["part": "snippet", "channelId":
"UCMztOaBEOOswwu0wHlchkeA", "key":
"AIzaSyBHzTMlp1FkiIQJxda5UgSunikzfnQWnwQ" ], encoding:
JSONEncoding.default, headers: nil).downloadProgress(queue:
DispatchQueue.global(qos: .utility)) { Progress in
print("progress: \(Progress.fractionCompleted)")
}
.validate { request ,response ,data in
return .success
}
.responseJSON { response in
print(response)
debugPrint(response)
}
when i am trying to print the response i am getting error "Domain=kCFErrorDomainCFNetwork Code=303
Change JSONEncoding.default to URLEncoding.default
These parameters are query parameters defined here, thus you should use URLEncoding instead of JSONEncoding

Set progressive view for multiple Alamofire calls in swift

In one Viewcontrollers, I have three Alamofire API calls...I wish to set progressive view's progress to 100% when the three API calls are completed?
PS: Also, can someone teach me how to do it for a single Alamofire API call too?
Thanks in advance.
Alamofire offering progress block for giving status about api progress status, you can use this to show your progress of you request or response like below for single api,
Alamofire.request("url", method: "httpMethod", parameters: "parameter", encoding: JSONEncoding.default, headers: "headers").downloadProgress(closure: { (progress) in
// Progress block called frequently during the lifecycle of api.
let fractionCompletedINpercentage = progress?.fractionCompleted * 100
}).validate().responseData(completionHandler: { (response) in
if response.result.isSuccess {
// Download success
} else if response.result.isFailure {
// Download failed
}
})
For handling multiple api, you can use Bool for each api and show your progress by taking minimum or average of fraction completed from all api progress.
Thanks
The download progress is available right in the Alamofire's doc
let utilityQueue = DispatchQueue.global(qos: .utility)
Alamofire.download("https://httpbin.org/image/png")
.downloadProgress(queue: utilityQueue) { progress in
print("Download Progress: \(progress.fractionCompleted)")
}
.responseData { response in
if let data = response.result.value {
let image = UIImage(data: data)
}
}
That said, it probably wouldn't work if the API response is gzipped or the content-length header isn't set.
Working method to use Alamofire
let strURL:String = "https://xxxx"
let parameters: Parameters = ["keyword": "current_timestamp"]
Alamofire.request(strURL, method: .post, parameters: parameters, encoding: URLEncoding.default).responseJSON { (response) in
print(response.data!)
print(response.result)
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
}

How to catch if any failure happens in Alamofire 4

I am calling my webservice in this way.
public func prepareUrl (baseUrl: String, appendString: String, bindedParams: String, isAuthorized: Bool, method: HTTPMethod, jsonBody: [String:String], callback: #escaping (String) ->Void> Void)
{
let dm=Datamanager.sharedInstance
let baseUrl=dm.globalUrl
let urlString=baseUrl!+appendString as String+bindedParams as String
print(urlString)
Alamofire.request(urlString, method: method, parameters: nil, encoding: JSONEncoding.default)
.downloadProgress(queue: DispatchQueue.global(qos: .utility)) { progress in
print("Progress: \(progress.fractionCompleted)")
}
.validate { request, response, data in
// Custom evaluation closure now includes data (allows you to parse data to dig out error messages if necessary)
return .success
}
.responseJSON { response in
debugPrint(response)
callback("success")
}
}
But how can I do error handling here. Even If I referred the github Alamofire 4.0 migration I don't have clear idea how to do it.
Please help me.
thanks
In Alamofire gitHub has the method:
You don't need the validate, Alamofire default validation is that 200 to 299 is success, you can get the error from the response.
public func prepareUrl (baseUrl: String, appendString: String, bindedParams: String, isAuthorized: Bool, method: HTTPMethod, jsonBody: [String:String], callback: #escaping (String) ->Void> Void)
{
let dm=Datamanager.sharedInstance
let baseUrl=dm.globalUrl
let urlString=baseUrl!+appendString as String+bindedParams as String
print(urlString)
Alamofire.request(urlString, method: method, parameters: nil, encoding: JSONEncoding.default)
.downloadProgress(queue: DispatchQueue.global(qos: .utility)) { progress in
print("Progress: \(progress.fractionCompleted)")
}
.responseJSON { response in
debugPrint(response)
switch response.result {
case .success:
callback("success")
case .failure(let error):
print(error)
}
}
}
Checkout the documentation

How to set method, header, parameter in Alamofire 4 and Swift 3

In past version of Alamofire, for send method,header and parameter I used to do like this:
Alamofire.request(.GET, URLRequest, headers:headers, parameters: parameters)
but version 4 and swift 3 is different.
How can I set method, send header & parameter?
The migration guide at Alamofire github explains this very well.
Take a look here:
// Alamofire 3
let parameters: [String: AnyObject] = ["foo": "bar"]
Alamofire.request(.GET, urlString, parameters: parameters, encoding: .JSON)
.progress { bytesRead, totalBytesRead, totalBytesExpectedToRead in
print("Bytes: \(bytesRead), Total Bytes: \(totalBytesRead), Total Bytes Expected: \(totalBytesExpectedToRead)")
}
.validate { request, response in
// Custom evaluation closure (no access to server data)
return .success
}
.responseJSON { response in
debugPrint(response)
}
// Alamofire 4
let parameters: Parameters = ["foo": "bar"]
Alamofire.request(urlString, method: .get, parameters: parameters, encoding: JSONEncoding.default)
.downloadProgress(queue: DispatchQueue.utility) { progress in
print("Progress: \(progress.fractionCompleted)")
}
.validate { request, response, data in
// Custom evaluation closure now includes data (allows you to parse data to dig out error messages if necessary)
return .success
}
.responseJSON { response in
debugPrint(response)
}
The migration guide explained well, but there are no headers in the example, just to avoid confusions, bellow I add the example of a GET request to add them.
Alamofire.request(URL, method: .get, parameters: parameters, headers: headers)
.validate { request, response, data in
return .success
}
.responseJSON { response in
switch response.result {
case .success:
// do something
break
case .failure(let error):
// handle error
break
}
}
I found this information in here so, go and check it there if you have question related with the headers in the request.

Alamofire POST request with progress

I'm using Alamofire to do a POST request.
As this POST request can take a while and I want to keep track of the progress and display it as a ProgressView.
Alamofire.request(.POST, ApiLink.create_post, parameters: parameters, encoding: .JSON)
.progress { (bytesRead, totalBytesRead, totalBytesExpectedToRead) -> Void in
println("ENTER .PROGRESSS")
println("\(totalBytesRead) of \(totalBytesExpectedToRead)")
self.progressView.setProgress(Float(totalBytesRead) / Float(totalBytesExpectedToRead), animated: true)
}
.responseJSON { (_, _, mydata, _) in
println(mydata)
}
However, I've noticed that the .progress block only get called after the post request has ended instead of getting called multiple times to actually keep track of the progress.
println("ENTER .PROGRESSS") gets called only once (at the end)
How can I make .progress works with Alamofire.request POST ?
Also : My parameters include a base64 encoded image string. I'm using a back-end Ruby on Rails to process the image. It's that process that is taking quite some time.
What you can do instead is first use the ParameterEncoding enum to generate the HTTPBody data. Then you can pull that data out and pass it off to the Alamofire upload method. Here's a modified version of your same function that compiles in a playground and instead uses the upload function.
struct ApiLink {
static let create_post = "/my/path/for/create/post"
}
let parameters: [String: AnyObject] = ["key": "value"] // Make sure this has your image as well
let mutableURLRequest = NSMutableURLRequest(URL: NSURL(string: ApiLink.create_post)!)
mutableURLRequest.HTTPMethod = Method.POST.rawValue
let encodedURLRequest = ParameterEncoding.JSON.encode(mutableURLRequest, parameters: parameters).0
let data = encodedURLRequest.HTTPBody!
let progressView = UIProgressView()
Alamofire.upload(mutableURLRequest, data)
.progress { _, totalBytesRead, totalBytesExpectedToRead in
println("ENTER .PROGRESSS")
println("\(totalBytesRead) of \(totalBytesExpectedToRead)")
progressView.setProgress(Float(totalBytesRead) / Float(totalBytesExpectedToRead), animated: true)
}
.responseJSON { _, _, mydata, _ in
println(mydata)
}
This will certainly have progress updates as #mattt originally mentioned in his comment above.
As #cnoon said you can use upload method to track progress with some modifications. Here is what exactly worked with me:
let jsonData = NSJSONSerialization.dataWithJSONObject(jsonObject, options: .PrettyPrinted)
Alamofire.upload(.POST, "API URL String", headers: ["Content-Type": "application/json"], data: jsonData)
.validate()
.responseJSON(completionHandler: { (response: Response<AnyObject, NSError>) in
//Completion handler code
})
.progress({ (bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) in
//Progress handler code
})
Note that you must set the "Content-Type" http header field value to "application/json" if the data is formatted as json to be decoded correctly at the backend.
There's a separate method in Alamofire to upload. Please check their documentation here.
They have sub-sections
Uploading with Progress
Uploading MultipartFormData
Which describes uploading.

Resources