Related
I am trying to convert my image into multipart form data but it will fetch error.
var request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
var boundary = generateBoundaryString()
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
var body = NSMutableData()
if self.img.image != nil {
var imageData = UIImagePNGRepresentation(self.img.image)
if imageData != nil {
body.appendString("--\(boundary)\r\n")
body.appendString("Content-Disposition: form-data; name=\"image\"; filename=\"image.png\"\r\n")
body.appendString("Content-Type: image/png\r\n\r\n")
body.appendData(imageData!)
body.appendString("\r\n")
}
}
body.appendString("--\(boundary)--\r\n")
request.setValue("\(body.length)", forHTTPHeaderField:"Content-Length")
request.HTTPBody = body
Please let me know how to convert UIImage into multipart form data and upload it to server in swift.
Try this code
func requestWith(endUrl: String, imageData: Data?, parameters: [String : Any], onCompletion: ((JSON?) -> Void)? = nil, onError: ((Error?) -> Void)? = nil){
let url = "http://google.com" /* your API url */
let headers: HTTPHeaders = [
/* "Authorization": "your_access_token", in case you need authorization header */
"Content-type": "multipart/form-data"
]
Alamofire.upload(multipartFormData: { (multipartFormData) in
for (key, value) in parameters {
multipartFormData.append("\(value)".data(using: String.Encoding.utf8)!, withName: key as String)
}
if let data = imageData{
multipartFormData.append(data, withName: "image", fileName: "image.png", mimeType: "image/png")
}
}, usingThreshold: UInt64.init(), to: url, method: .post, headers: headers) { (result) in
switch result{
case .success(let upload, _, _):
upload.responseJSON { response in
print("Succesfully uploaded")
if let err = response.error{
onError?(err)
return
}
onCompletion?(nil)
}
case .failure(let error):
print("Error in upload: \(error.localizedDescription)")
onError?(error)
}
}
}
Try below code :
func requestAPIWithImage( parameters: Parameters,url: URLConvertible,Completion: #escaping (_ success: Bool,_ response: AnyObject) -> Void) {
Alamofire.upload(multipartFormData: { (multipartFormData) in
print(parameters)
if Array(parameters.keys).contains(Keys.Image) {
multipartFormData.append(UIImageJPEGRepresentation((parameters)[Keys.Image] as! UIImage, 1)!, withName: "image", fileName: "swift_file.jpeg", mimeType: "image/jpeg")
}
for (key, value) in parameters {
print(key,value)
if key != Keys.Image{
multipartFormData.append((value as AnyObject).data(using: String.Encoding.utf8.rawValue)!, withName: key)
}
}
}, to:url)
{ (result) in
switch result {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (progress) in
})
upload.responseJSON { response in
print(response.result)
self.getValidDict(result: response.result, completion: { (dict, error) in
var dict = dict
if dict == nil {
dict = NSDictionary.init(dictionary:
[kBaseMessageKey: error?.localizedDescription ?? "Some error has been occured",
kBaseStatusKey: false])
}
Completion(true,dict![Keys.result]! as AnyObject)
})
}
case .failure(let encodingError):
Completion(false,encodingError.localizedDescription as AnyObject)
break
}
}
}
Try this code, i hope it helps you.
let url = "RequestURL"
let img = UIImage(contentsOfFile: fullPath)
let data: NSData = UIImageJPEGRepresentation(img, 1)
sendFile(url,
fileName:"one.jpg",
data:data,
completionHandler: completionHandler:{
(result:Bool, isNoInternetConnection:Bool) -> Void in
// ...
NSLog("Complete: \(result)")
}
)
func sendFile(
urlPath:String,
fileName:String,
data:NSData,
completionHandler: (NSURLResponse!, NSData!, NSError!) -> Void){
var url: NSURL = NSURL(string: urlPath)!
var request1: NSMutableURLRequest = NSMutableURLRequest(URL: url)
request1.HTTPMethod = "POST"
let boundary = generateBoundary()
let fullData = photoDataToFormData(data,boundary:boundary,fileName:fileName)
request1.setValue("multipart/form-data; boundary=" + boundary,
forHTTPHeaderField: "Content-Type")
// REQUIRED!
request1.setValue(String(fullData.length), forHTTPHeaderField: "Content-Length")
request1.HTTPBody = fullData
request1.HTTPShouldHandleCookies = false
let queue:NSOperationQueue = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(
request1,
queue: queue,
completionHandler:completionHandler)
}
// this is a very verbose version of that function
// you can shorten it, but i left it as-is for clarity
// and as an example
func photoDataToFormData(data:NSData,boundary:String,fileName:String) -> NSData {
var fullData = NSMutableData()
// 1 - Boundary should start with --
let lineOne = "--" + boundary + "\r\n"
fullData.appendData(lineOne.dataUsingEncoding(
NSUTF8StringEncoding,
allowLossyConversion: false)!)
// 2
let lineTwo = "Content-Disposition: form-data; name=\"image\"; filename=\"" + fileName + "\"\r\n"
NSLog(lineTwo)
fullData.appendData(lineTwo.dataUsingEncoding(
NSUTF8StringEncoding,
allowLossyConversion: false)!)
// 3
let lineThree = "Content-Type: image/jpg\r\n\r\n"
fullData.appendData(lineThree.dataUsingEncoding(
NSUTF8StringEncoding,
allowLossyConversion: false)!)
// 4
fullData.appendData(data)
// 5
let lineFive = "\r\n"
fullData.appendData(lineFive.dataUsingEncoding(
NSUTF8StringEncoding,
allowLossyConversion: false)!)
// 6 - The end. Notice -- at the start and at the end
let lineSix = "--" + boundary + "--\r\n"
fullData.appendData(lineSix.dataUsingEncoding(
NSUTF8StringEncoding,
allowLossyConversion: false)!)
return fullData
}
I implemented Upload image using Multi-part in Swift 4:
Here is the code. Please have a look
func uploadImageToServerFromApp(nameOfApi : NSString, parameters : NSString, uploadedImage : UIImage, withCurrentTask :RequestType, andDelegate :AnyObject)->Void {
if self.isConnectedToNetwork(){
currentTask = withCurrentTask
let myRequestUrl = NSString(format: "%#%#%#",GlobalConstants.KBaseURL,nameOfApi,parameters)
let url = (myRequestUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed))!
var request : NSMutableURLRequest = NSMutableURLRequest()
request = URLRequest(url: URL(string:url as String)!) as! NSMutableURLRequest
request.httpMethod = "POST"
//define the multipart request type
request.setValue("multipart/form-data", forHTTPHeaderField: "Content-Type")
let image_data = UIImagePNGRepresentation(uploadedImage)
if(image_data == nil){
return
}
let body = NSMutableData()
let fname = "image.png"
let mimetype = "image/png"
//define the data post parameter
body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Disposition:form-data; name=\"image\"\r\n\r\n".data(using: String.Encoding.utf8)!)
body.append("hi\r\n".data(using: String.Encoding.utf8)!)
body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Disposition:form-data; name=\"image\"; filename=\"\(fname)\"\r\n".data(using: String.Encoding.utf8)!)
body.append("Content-Type: \(mimetype)\r\n\r\n".data(using: String.Encoding.utf8)!)
body.append(image_data!)
body.append("\r\n".data(using: String.Encoding.utf8)!)
body.append("--\(boundary)--\r\n".data(using: String.Encoding.utf8)!)
request.httpBody = body as Data
let session = URLSession.shared
let task = session.dataTask(with: request as URLRequest) { (data, response, error) in
guard let data = data, error == nil else { // check for fundamental networking error
// print("error=\(String(describing: error))")
self.showAlertMessage(title: "App name", message: "Server not responding, please try later")
return
}
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))")
self.delegate?.internetConnectionFailedIssue()
}else{
do {
self.responseDictionary = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! NSDictionary
// self.Responsedata = data as NSData
//self.responseDictionary = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as! [String: AnyObject] as NSDictionary;
self.delegate?.responseReceived()
} catch {
//print("error serializing JSON: \(error)")
}
}
}
task.resume()
}else{
// print("Internet Connection not Available!")
self.showAlertMessage(title: "App Name", message: "No Internet Connection..")
}}
In my project I want to convert Json String from server to Array but Unable to convert, But when I hard code(Directly gave the particular json string) the json string means that will be convert. Please help me to find the issue..
Here I gave the code what i am tried.
var params = NSMutableDictionary()
params = [
"inspectionLogId": inspectionLogIdStr
]
let manager = AFHTTPSessionManager()
manager.requestSerializer = AFJSONRequestSerializer()
manager.responseSerializer = AFHTTPResponseSerializer()
manager.responseSerializer.acceptableContentTypes = NSSet(array: ["text/plain", "text/html", "application/json"]) as Set<NSObject> as Set<NSObject>! as! Set<String>?
manager.requestSerializer.setValue("", forHTTPHeaderField: "apptoken")
manager.requestSerializer.setValue(strAppToken, forHTTPHeaderField: "token")
let urlString:NSString = NSString(format: "%#%#", ApiConstantFile().baseUrlProperty,ApiConstantFile().getTemplateDataUrl)
print(urlString)
manager.get(urlString as String, parameters: params, progress: nil, success: {
(operation, responseObject) in
self.stopAnimation()
let jsonstring = String(data: responseObject! as! Data, encoding: String.Encoding.utf8)
print("jsonstring is:, \(jsonstring!)")
let data = jsonstring!.data(using: .utf8)!
print(data)
do {
if (try JSONSerialization.jsonObject(with: data, options : .allowFragments) as? [Dictionary<String,Any>]) != nil {
let jsonArray = try JSONSerialization.jsonObject(with: data, options : .allowFragments) as! [Dictionary<String,Any>]
print(jsonArray)
} else {
print("bad json")
}
} catch {
print(error)
}
}, failure: {
(operation, error) in
self.stopAnimation()
print(error)
self.alert(message: error.localizedDescription)
})
when I print the json string means they show to string:
"[{\"propertyId\":\"1\",\"inspectionTemplateId\":1118,\"value\":[{\"widgetControllerId\":141,\"value\":\"Flood Summary Name\"},{\"widgetControllerId\":142,\"value\":\"Did the property flood?\"},{\"widgetControllerId\":143,\"value\":\"no\"}]}]"
But when I directly gives the string means it will convert to array.
let jsonstring = "[{\"propertyId\":\"1\",\"inspectionTemplateId\":1118,\"value\":[{\"widgetControllerId\":141,\"value\":\"Flood Summary Name\"},{\"widgetControllerId\":142,\"value\":\"Did the property flood?\"},{\"widgetControllerId\":143,\"value\":\"no\"}]}]"
Just replace AFHTTPResponseSerializer with AFJSONResponseSerializer like this:
var params = NSMutableDictionary()
params = [
"inspectionLogId": inspectionLogIdStr
]
let manager = AFHTTPSessionManager()
manager.requestSerializer = AFJSONRequestSerializer()
manager.responseSerializer = AFJSONResponseSerializer()
manager.requestSerializer.setValue("", forHTTPHeaderField: "apptoken")
manager.requestSerializer.setValue(strAppToken, forHTTPHeaderField: "token")
let urlString:NSString = NSString(format: "%#%#", ApiConstantFile().baseUrlProperty,ApiConstantFile().getTemplateDataUrl)
print(urlString)
manager.get(urlString as String, parameters: params, progress: nil, success: {
(operation, responseObject) in
self.stopAnimation()
print(responseObject)
}, failure: {
(operation, error) in
self.stopAnimation()
print(error)
self.alert(message: error.localizedDescription)
})
manager.post(urlString, parameters: perameter, progress: nil,
success:
{
requestOperation, response in
SVProgressHUD.dismiss()
let json = try! JSONSerialization.jsonObject(with: (response as! NSData) as Data, options:.allowFragments) as! NSDictionary
self.listData = json["Result"] as! [NSDictionary]
print(self.listData)
self.tableViewOutlet.reloadData()
},
failure:
{
requestOperation, error in
print(error.localizedDescription)
})
For image upload, you can use multipart.
manager.responseSerializer.acceptableContentTypes = ["text/html"]
manager.post(url as String, parameters: dic, constructingBodyWith: { (data) in
if imgData != nil
{
data.appendPart(withFileData: imgData!, name: "image", fileName: imgName as String , mimeType: "image/jpeg")
}
}, progress: nil, success: { (sessiondata, result) in
UIApplication.shared.isNetworkActivityIndicatorVisible = true
let dict = result as! Dictionary<String, AnyObject>
print(dict)
if (dict["status"]?.boolValue == true)
{
block(dict as NSDictionary?)
}
else{
block(dict as NSDictionary?)
}
}) { (data, result) -> Void in
let errorDict = ["error": data?.error?.localizedDescription as AnyObject]
UIApplication.shared.isNetworkActivityIndicatorVisible = false
block(errorDict as NSDictionary?)
}
Try this :
let manager = AFHTTPRequestOperationManager()
let url = "http://path/to/server"
let URL : NSURL = NSURL(string: url)!
let req : NSURLRequest = NSURLRequest(URL: URL)
let fileURL = NSURL(string: "file:///var/mobile/Media/DCIM/102APPLE/IMG_2623.PNG")// change your image url
manager.POST( url, parameters: nil,
constructingBodyWithBlock: { (data: AFMultipartFormData!) in
do{
_ = try data.appendPartWithFileURL(fileURL!, name: "uploaded_file", fileName: "image.png", mimeType: "image/png")
}catch{
}
},
success: { (operation: AFHTTPRequestOperation!, responseObject: AnyObject!) in
print("\(responseObject)")
},
failure: { (operation: AFHTTPRequestOperation!, error: NSError!) in
print("\(error.localizedDescription)")
})
Use below function to upload image with other parameter to server:
typealias MultipartFormDataBlock = (_ multipartFormData : MultipartFormData?) -> Void
typealias CompletionBlock = (_ response: Any?, _ error: Error?) -> Void
func multiPartRequestWithUrl(url: String, parameters: Dictionary<String,Any>?, multiPartFormDataBlock: MultipartFormDataBlock?, completion: CompletionBlock?) -> Void {
var param : Dictionary! = parameters ?? Dictionary()
print("Param = \(param)")
Alamofire.upload(multipartFormData: { (multiPartFormData) in
multiPartFormDataBlock?(multiPartFormData)
if param != nil {
for (key, value) in param! {
multiPartFormData.append("\(value)".data(using: .utf8)!, withName: key)
}
}
}, to: url, encodingCompletion:{encodingResult in
switch encodingResult {
case .success(let upload, _, _):
upload.responseJSON { response in
switch response.result {
case .success(let value):
handleResponse(response: value, completion: completion)
case .failure(let error):
print(error.localizedDescription)
completion?(nil, error)
}
}
case .failure(let encodingError):
completion?(nil, encodingError)
}
})
}
For New function with AFNetworking
+ (NSURLSessionDataTask *)multiPartRequestWithURL:(NSString *)strUrl parameters:(NSDictionary *)parameters constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))formData progress:(void (^)(NSProgress *progress))progressBlock requestCompletionBlock:(requestCompletionBlock)requestCompletionBlock {
NSMutableDictionary *dictParameters = [parameters mutableCopy];
if(!dictParameters) {
dictParameters = [NSMutableDictionary dictionary];
}
dictParameters[#"lang"] = [AppUtility CURRENT_SELECTED_LANGUAGE];
NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:#"POST" URLString:strUrl parameters:dictParameters constructingBodyWithBlock:formData error:nil];
[request setTimeoutInterval:3600];
NSURLSessionDataTask *dataTask = [self request:request uploadProgress:^(NSProgress *uploadProgress) {
dispatch_async(dispatch_get_main_queue(), ^{
if(progressBlock) {
progressBlock(uploadProgress);
}
});
} downloadProgress:nil requestCompletionBlock:^(id responseObject, NSError *error) {
if(requestCompletionBlock) {
requestCompletionBlock(responseObject, error);
}
}];
[dataTask resume];
return dataTask;
}
Upload image using AFNetworking in Swift 4
let urlPath1 = "Path url here"
let manager = AFHTTPRequestOperationManager()
var Timestamp: String {
return "\(NSDate().timeIntervalSince1970 * 1000)"
}
let operation = manager.post(urlPath1 as String, parameters: dictData, constructingBodyWith: { (data:AFMultipartFormData!) -> Void in
if image != nil {
data.appendPart(withFileData: UIImagePNGRepresentation(image!)!, name: imageName as String, fileName: "\(Timestamp).png", mimeType: "image/png")
}
}, success: { (operation, responseObject) -> Void in
success(responseObject as AnyObject)
}) { (operation, error) -> Void in
print(error, terminator: "")
}
operation?.start()
}
In Swift 5 use following:
image.pngData()
or
forImage.jpegData(compressionQuality: 0.5)
based on your requirement.
I need to upload an image to the server endpoint where the structure has to be as following:
{ "image": { "file": imageData }, "access_token": access_token }
How can I send such a request using NSURLSession (or maybe even Alamofire or AFNetworking)?
You cannot just include binary image data in a JSON request. JSON requires text representation, so if you do this, you must convert it to string (e.g. base64 encoding), use that in the JSON, and then the server code would presumably convert the base64 string back to binary data before attempting to use it.
But if you were base64 encoding of the image, it might look something like:
// get image data
let imageData = UIImagePNGRepresentation(image)
// convert to base64
let base64String = imageData.base64EncodedStringWithOptions(nil)
// build parameters
let parameters = ["image": ["file" : base64String], "access_token" : accessToken]
// get JSON
var error: NSError?
let data = NSJSONSerialization.dataWithJSONObject(parameters, options: nil, error: &error)
assert(data != nil, "Unable to serialize \(error)")
// build request
let url = NSURL(string: "http://example.com/upload")!
let request = NSMutableURLRequest(URL: url)
request.addValue("text/json", forHTTPHeaderField: "Content-Type")
request.HTTPMethod = "POST"
let task = NSURLSession.sharedSession().uploadTaskWithRequest(request, fromData: data) { data, response, error in
// check for basic connectivity errors
if error != nil {
println("error: \(error)")
return
}
// check for server errors
if let httpResponse = response as? NSHTTPURLResponse, let statusCode = httpResponse.statusCode as Int? {
if statusCode != 200 {
println("status code is \(statusCode)")
}
}
// check for details of app-level server response, e.g. if JSON that was dictionary:
var parseError: NSError?
if let responseObject = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &parseError) as? [String : AnyObject] {
println(responseObject)
} else {
println("JSON parse failed: \(parseError)")
println("response was: \(response)")
let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("responseString was: \(responseString)")
}
}
task.resume()
If you use Alamofire, this is simplified:
// build parameters
let parameters = ["image": ["file" : base64String], "access_token" : accessToken] as [String : AnyObject]
// build request
let urlString = "http://example.com/upload"
Alamofire.request(.POST, urlString, parameters: parameters, encoding: .JSON)
.responseJSON(options: nil) { request, response, responseObject, error in
if error != nil {
println(error)
} else {
println(responseObject)
}
}
But both of the above are making assumptions about the nature of the response, that the server is base64 decoding the image data from the JSON, etc., but hopefully this illustrates the basic patterns.
Alternatively, use an application/x-www-form-urlencoded request, in which you can send binary data as illustrated here.
Found a solution using AFNetworking with help from https://stackoverflow.com/a/11092052/3871476
For others looking for the solution.
let manager = AFHTTPRequestOperationManager(baseURL: NSURL(string: url))
let request = manager.POST(url, parameters: param, constructingBodyWithBlock: {(formData: AFMultipartFormData!) -> Void in
formData.appendPartWithFileData(imgdata, name: "image[file]", fileName: "photo.jpeg", mimeType: "image/jpeg")
}, success: {(operation: AFHTTPRequestOperation!, responseObject: AnyObject!) -> Void in
//Success
}, failure: {(operation: AFHTTPRequestOperation!, error: NSError!) -> Void in
//Failure
println(error.localizedDescription)
})
The trick was to use the "image[file]" parameter.
Try this:
var request = NSMutableURLRequest(URL: NSURL(string: "https://\(IP):\(port)/")!)
var response: NSURLResponse?
var error: NSError?
//Adding the JSON String in HTTP Body
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(jsonString, options: nil, error: &error)
request.timeoutInterval = (number as! NSTimeInterval)
request.HTTPMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("gzip", forHTTPHeaderField: "Accept-encoding")
let urlData = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error)
I am trying to send a multi-part post request which includes an image. The following code works fine:
manager.POST( apiUrl + "/location/add",
parameters: parameters,
constructingBodyWithBlock: { (formData : AFMultipartFormData!) -> Void in
// formData.appendPartWithFileURL(NSURL(string: location.imagePath!), name: "image", error: nil)},
formData.appendPartWithFileData(img, name: imgParam, fileName: "randomimagename.jpg", mimeType: "image/jpeg")},
success: { (operation: AFHTTPRequestOperation!,responseObject: AnyObject!) in
println("JSON: " + responseObject.description)
var dict = responseObject as NSDictionary
let json = JSONValue(dict)
var message = ""
if let msg = json["message"].string {message = msg}
var success = false
if let s = json["success"].bool {
callback(success: success, msg: message)
}
},
failure: { (operation: AFHTTPRequestOperation!,error: NSError!) in
println("Error: " + error.localizedDescription)
var apiError = ApiError()
apiError.noConnection = true
errorCallback(apiError: apiError)
})
I want to use appendPartWithFileURL instead of appendPartWithFileData. If I replace the 5th line wiht the line which is commented out in the code above, I get the following compiler error:
Extra argument 'constructingBodyWithBlock' in call
Does anybody know how to resolve this?
edit: Found a (very, very, very strange) solution. Replace the line
formData.appendPartWithFileURL(NSURL(string: location.imagePath!), name: "image", error: nil)},
with
var temp = formData.appendPartWithFileURL(NSURL(string: location.imagePath!), name: "image", error: nil)},
I didn't change anything beside adding var temp =. I have no idea why this is working, but it does. Seems to be a strange bug.
If you haven't solved this problem yet, try casting location.imagePath to String.
I had the same problem till I've added as String in the following code:
func uploadFile(file: NSData, url: String, formData: NSDictionary, parameters: NSDictionary, completion: AnyObject -> Void, failure: NSError -> Void) {
operationManager.requestSerializer = AFJSONRequestSerializer() as AFHTTPRequestSerializer
if operationManager.reachabilityManager.networkReachabilityStatus != .NotReachable {
operationManager.POST(url, parameters: parameters, constructingBodyWithBlock: { (data) in
data.appendPartWithFileData(file, name: formData["fileName"] as String, fileName: formData["fileName"] as String, mimeType: formData["mimeType"] as String)
}, success: { (operation, responseObject) in
completion(responseObject)
}, failure: { (operation, error) in
failure(error)
})
} else {
showReachabilityAlert()
}
}
Hope it helps.
I kept receiving this error until I cast the URL as a string. Here's what I was doing (and receiving the error while doing so):
let manager = AFHTTPSessionManager()
let fullUrl = NSURL(string: name, relativeToURL: NSURL(string: apiBaseEndpoint))
manager.POST(fullUrl, parameters: nil, constructingBodyWithBlock: { (formData) in
formData.appendPartWithFormData(file, name: "image")
}, success: { (operation, responseObject) in
NSLog("hit success")
}, failure: { (operation, error) in
NSLog("hit the error")
})
To resolve the issue, I simply changed the assignment of fullUrl to take a string rather than NSURL by adding .absoluteString.
let fullUrl = NSURL(string: name, relativeToURL: NSURL(string: apiBaseEndpoint)).absoluteString