Swift + ios 9, sending post data with base64 image data - node.js

I have looked at the different questions related to send a post request with NS on swift. I am having issues however with the following code where the responding server doesn't even see it as being a post request.
What am I missing:
var request = NSMutableURLRequest(URL: NSURL(string: url)!)
request.HTTPMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var imageData = UIImageJPEGRepresentation(img, 0.6)
var base64String = imageData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0)) // encode the image
var err: NSError? = nil
var params = ["image":[ "content_type": "image/jpeg", "filename":"\(self.riderid).jpg", "file_data": base64String]]
println("Image params \(params)")
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: NSJSONWritingOptions(0), error: &err)!
var task = session.dataTaskWithRequest(request, completionHandler: { data, response, error -> Void in
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
var err: NSError?
println("Image Response \(err) \(data)")
// process the response
var hoge = JSON(data: data!)
println("Image Response \(hoge)")
})

You need task.resume() after task block.

I know it's late replay but maybe it's help someone
var base64String = Detail.image.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
print(base64String)
var base64String2 = base64String.replacingOccurrences(of: "+", with: "%2B", options: NSString.CompareOptions.literal, range: nil)
base64String2 = base64String.replacingOccurrences(of: "/", with: "%2F", options: NSString.CompareOptions.literal, range: nil)
print(base64String2)
Do something like this
func insertDoctor_Detailmaster(_ Detail:DoctorDetail, isInsertOrUpdate:String){
var request:NSMutableURLRequest!
var postString:String
var base64String = Detail.image.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
print(base64String)
var base64String2 = base64String.replacingOccurrences(of: "+", with: "%2B", options: NSString.CompareOptions.literal, range: nil)
base64String2 = base64String.replacingOccurrences(of: "/", with: "%2F", options: NSString.CompareOptions.literal, range: nil)
print(base64String2)
if(isInsertOrUpdate == "insert"){
request = NSMutableURLRequest(url: URL(string: link.commonlink + "insert_doctor_master.php")!)
param = "doctor_id=\(Detail.doctor_id)&first_name=\(Detail.first_name)&last_name=\(Detail.last_name)&mid_name=\(Detail.mid_name)&speciality=\(Detail.speciality)&dob=\(Detail.dob)&gender=\(Detail.gender)&address_id=\(Detail.address_id)&mobile_number=\(Detail.mobile_number)&user_image=\(base64String2)"
_ = SD.executeChange(sqlStr: "INSERT INTO doctor_master (doctor_id, first_name,last_name, mid_name, dob, gender,doctorImage,speciality, address_id, mobileNumber) VALUES ('\(Detail.doctor_id)','\(Detail.first_name)','\("")','\(Detail.mid_name)','\(Detail.dob)','\(Detail.gender)','\(base64String)','\(Detail.speciality)','\(Detail.mobile_number)','\(Detail.mobile_number)')")
}else{
request = NSMutableURLRequest(url: URL(string: link.commonlink + "update_doctor_master.php")!)
param = "doctor_id=\(Detail.doctor_id)&first_name=\(Detail.first_name)&last_name=\(Detail.last_name)&mid_name=\(Detail.mid_name)&speciality=\(Detail.speciality)&dob=\(Detail.dob)&gender=\(Detail.gender)&address_id=\(Detail.address_id)&mobile_number=\(Detail.mobile_number)&\(base64String2)"
_ = SD.executeChange(sqlStr: "UPDATE doctor_master SET doctor_id = \(Detail.doctor_id), firstName ='\(Detail.first_name)',last_name = '\("")', mid_name ='\(Detail.mid_name)', dob ='\(Detail.dob)',gender = '\(Detail.gender)',doctorImage='\(base64String)',speciality='\(Detail.speciality)', address_id ='\(Detail.mobile_number)',mobileNumber = '\(Detail.mobile_number)'")
}
print(param)
postString = "q=\(AGS().encrypt(PlainText: param!))"
request.httpMethod = "POST"
request.httpBody = postString.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
}
print("response = \(response)")
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print(responseString!)
res.variable.dosage = responseString as! String
}
task.resume()
print(postString)
}

Make sure your Session object's configuration for your request and as JMStudios.jrichardson said , write task.resume() after task block.

Related

add/modify/edit the photo's exif in swift

I am building an app which can add/modify/edit the exif after the photo filtered. The photo miss all the exif after adding filter. I have try added the new exif to the photo by attempting using the code below, which is not work. The exif still blank in the Mac App - Photos. How to fix it?
THX
//Code below
imageData = UIImageJPEGRepresentation(outp, 1.0)
let imageSource = CGImageSourceCreateWithData(imageData! as CFData, nil)
let filePath = NSTemporaryDirectory().appending("example.jpg")
let fileURL = URL.init(fileURLWithPath: filePath)
var imageInfo = CGImageSourceCopyPropertiesAtIndex(imageSource!, 0, nil) as! Dictionary<CFString, Any>
var exifDictionay = Dictionary<CFString, Any>()
exifDictionay = imageInfo[kCGImagePropertyExifDictionary] as! Dictionary<CFString, Any>
exifDictionay[kCGImagePropertyExifExposureTime] = "1/3"
exifDictionay[kCGImagePropertyExifISOSpeed] = "200"
exifDictionay[kCGImagePropertyExifFNumber] = "2.4"
exifDictionay[kCGImagePropertyExifApertureValue] = "3.5"
exifDictionay[kCGImagePropertyExifFlash] = "On"
imageInfo[kCGImagePropertyExifDictionary] = exifDictionay
let UTI = CGImageSourceGetType(imageSource!)
let newImageData = NSMutableData()
CGImageDestinationAddImageFromSource(destination!, imageSource!, 0, imageInfo as CFDictionary)
CGImageDestinationFinalize(destination!)
PHPhotoLibrary.shared().performChanges({
let creationRequest = PHAssetCreationRequest.forAsset()
creationRequest.addResource(with: PHAssetResourceType.photo, data: newImageData as Data, options: nil)
}, completionHandler: nil)

NodeJs : Any way to bypass querystring.stringify with empty Object?

I am working currently on a project that requires to send custom GET HTTP requests.
I am using the default querystring builder : the Documentation
const querystring = require('querystring');
The problem is for Object (probably also for empty array) such as
extendTypes={}
is serialiazed as :
extendTypes=
The expected result :
extendTypes={}
or its URI encoded version :
extendTypes%3D%7B%7D
So , how can I ever hope to do that ? If It is impossible with the in-builded module, which one could do what I want.
Here is my full code if you want :
function generateGetRequest(dataMap, url) {
let queryParams = {};
let uriParams = {};
for (let [key, value] of dataMap) {
// if value is an object or an array
if (value instanceof Object || value instanceof Array) {
uriParams[key] = value;
} else {
// param working for superagent
queryParams[key] = value;
}
}
let queryParamsUri = querystring.stringify(uriParams);
console.log(queryParamsUri);
let finalUrl = url + ( (Object.keys(uriParams).length > 0) ? "?" + queryParamsUri : "");
}
I finally found a workaround , if someone wants to know :
let request = require("superagent");
function generateGetRequest(dataMap, url) {
let queryParams = {};
let queryParamsUri = "";
let isFirstParam = true;
for (let [key, value] of dataMap) {
// if value is an object or an array
if (value instanceof Object) {
// Workaround for empty object or array = https://github.com/nodejs/node/issues/12234
queryParamsUri += ((!isFirstParam) ? "&": "") + key + "=" + JSON.stringify(value);
// for next call
isFirstParam = false;
} else {
// param working for superagent
queryParams[key] = value;
}
}
let finalUrl = url + ( (!isFirstParam) ? "?" + queryParamsUri : "");
return request
.get(finalUrl)
.query(queryParams);
}

get value of nested array alamofire swift 3

I need to get the nested array values, I need the user data and I need token data. I need this data because I need to initialize session variables to be able to use them in my application.
For example the user name, fotografia, managed to get the data rc and msg that are in the main array but I could not get the values ​​of nested arrays
["rc": 00,
"user": {
"__v" = 0;
deviceId = "";
email = "john#gmail.com";
fullName = "SMITH JOHN ";
lastName = "SMITH ";
modifiedAt = "2016-12-16T06:08:58.856Z";
name = "JOHN ";
photo = "";
provider = "";
"provider_id" = "";
status = 01;
tel = 3333333333;
typeUser = USER;
username = "john#gmail.com";
}, "token": {
"__v" = 0;
"_id" = 585384e3ccc4;
createdAt = "2016-12-16T08:10:03.407Z";
userId = 585384e3ccc4;
value = Z4WedlAzhdkap;
}, "msg": success]
#IBAction func btnLogin(_ sender: Any) {
let gsUtil=GSUtil()
let user = txtUser.text!
let password = txtPass.text!
let credentialData = "\(user):\(password)".data(using: String.Encoding.utf8)!
let base64Credentials = credentialData.base64EncodedString(options: [])
let headers = ["Authorization": "Basic \(base64Credentials)"]
Alamofire.request(gsUtil.getCompleteURI()+"user/auth/",
method: .post,
parameters: nil,
encoding: URLEncoding.default,
headers:headers)
.validate()
.responseJSON { response in
if response.result.value != nil{
let json = response.result.value as? [String: Any]
let rc=json?["rc"]
let msg=json?["msg"]
if rc as? String=="00"
{
self.showMessage(msg: msg as! String)
}
}else{
self.showMessage(msg: "Error en los datos")
}
}
}
I do not really get the problem. You already pretty much did what you need to do (only one step further):
I would start by getting rid of all the pesky optionals using a lot of if lets:
if let json = input as? [String: Any] {
let msg = json["msg"]
if let rc = json["rc"] as? String, rc == "00" {
self.showMessage(msg: msg as! String)
}
if let user = json["user"] as? [String : Any] {
print(user)
}
if let token = json["token"] as? [String : Any] {
print(token)
}
} else {
self.showMessage(msg: "Error en los datos")
}

Instagram sharing not working on iOS 9

This worked fine on iOS 8, but on iOS 9 the UIDocumentInteractionController does appear with the option Copy to Instagram. Pressing it just dismisses the controller.
Any feedback would be appreciated.
Thanks,
var docController = UIDocumentInteractionController()
let instagramURL = NSURL(string: "instagram://app")
if(UIApplication.sharedApplication().canOpenURL(instagramURL!)) {
var imagePost = cropped
let fullPath = documentsDirectory().stringByAppendingString("insta.igo")
var imageData = UIImagePNGRepresentation(imagePost!)!.writeToFile(fullPath, atomically: true)
let rect = CGRectMake(0, 0, 0, 0)
self.docController.UTI = "com.instagram.exclusivegram"
let igImageHookFile = NSURL(string: "file://\(fullPath)")
self.docController = UIDocumentInteractionController(URL: igImageHookFile!)
self.docController.presentOpenInMenuFromRect(rect, inView: self.view, animated: true)
}
func documentsDirectory() -> String {
let documentsFolderPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0]
return documentsFolderPath
}
The way iOS9 reads it when declaring "insta.igo", now needs to have the "/"
let fullPath = documentsDirectory().stringByAppendingString("/insta.igo")
Complete code
var docController = UIDocumentInteractionController()
let instagramURL = NSURL(string: "instagram://app")
if(UIApplication.sharedApplication().canOpenURL(instagramURL!)) {
var imagePost = cropped
let fullPath = documentsDirectory().stringByAppendingString("/insta.igo")
var imageData = UIImagePNGRepresentation(imagePost!)!.writeToFile(fullPath, atomically: true)
let rect = CGRectMake(0, 0, 0, 0)
self.docController.UTI = "com.instagram.exclusivegram"
let igImageHookFile = NSURL(string: "file://\(fullPath)")
self.docController = UIDocumentInteractionController(URL: igImageHookFile!)
self.docController.presentOpenInMenuFromRect(rect, inView: self.view, animated: true)
}
func documentsDirectory() -> String {
let documentsFolderPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0]
return documentsFolderPath
This solution provided by Andy Shephard worked for me:
https://stackoverflow.com/a/32616355/1500708

Bill Filtering only returns default 10 sorted records without doing any filtering from QBO

Please find the below code for for filtering bills, which returns only 10 sorted records even I passed the resultperpage>10.
public IEnumerable<Intuit.Ipp.Data.Qbo.Bill> FilterBills(DataServices dataServices, int startPage, int resultsPerPage, DateTime After, DateTime Before)
{
Intuit.Ipp.Security.OAuthRequestValidator oAuthRequestValidator = ((Intuit.Ipp.Security.OAuthRequestValidator)dataServices.ServiceContext.RequestValidator);
OAuthConsumerContext consumerContext = new OAuthConsumerContext
{
ConsumerKey = oAuthRequestValidator.ConsumerKey,
SignatureMethod = SignatureMethod.HmacSha1,
ConsumerSecret = oAuthRequestValidator.ConsumerSecret
};
OAuthSession oSession = new OAuthSession(consumerContext, "https://oauth.intuit.com/oauth/v1/get_request_token",
"https://workplace.intuit.com/Connect/Begin",
"https://oauth.intuit.com/oauth/v1/get_access_token");
oSession.AccessToken = new TokenBase
{
Token = oAuthRequestValidator.AccessToken,
ConsumerKey = oAuthRequestValidator.ConsumerKey,
TokenSecret = oAuthRequestValidator.AccessTokenSecret
};
var body = "PageNum={0}&ResultsPerPage={1}&Filter=LastUpdatedTime :AFTER: {2} :AND: LastUpdatedTime :BEFORE: {3} & Sort=LastUpdatedTime HighToLow";
body = String.Format(body, startPage, resultsPerPage, After.ToString("yyyy-mm-ddTHH:MM:ssz"), Before.ToString("yyyy-mm-ddTHH:MM:ssz"));
IConsumerRequest conReq = oSession.Request();
conReq = conReq.Post().WithRawContentType("application/x-www-form-urlencoded").WithRawContent(System.Text.Encoding.ASCII.GetBytes(body)); ;
conReq = conReq.ForUrl(dataServices.ServiceContext.BaseUrl + "bills/v2/" + dataServices.ServiceContext.RealmId);
conReq = conReq.SignWithToken();
Intuit.Ipp.Data.Qbo.SearchResults searchResults = (Intuit.Ipp.Data.Qbo.SearchResults)dataServices.ServiceContext.Serializer.Deserialize<Intuit.Ipp.Data.Qbo.SearchResults>(conReq.ReadBody());
IEnumerable<Intuit.Ipp.Data.Qbo.Bill> SearchResult = ((Intuit.Ipp.Data.Qbo.Bills)(searchResults.CdmCollections)).Bill;
return SearchResult;
}
After sending the request i m getting the respose as 10 sorted bill record without getting any error. I am using IPPDotNetDevKit 2.1.12.0 version.
Please Look into this filtering problem.
The OAuth parameters are being passed in the body of the request in your example above and overwriting your request body, so it is defaulting to PageNum=1&ResultsPerPage=20. Also, the date is formatted incorrectly. Here is a code sample that will work.
public IEnumerable<Intuit.Ipp.Data.Qbo.Bill> FilterBills(DataServices dataServices, int startPage, int resultsPerPage, DateTime After, DateTime Before)
{
StringBuilder requestXML = new StringBuilder();
StringBuilder responseXML = new StringBuilder();
var requestBody =
"PageNum={0}&ResultsPerPage={1}&Filter=LastUpdatedTime :AFTER: {2} :AND: LastUpdatedTime :BEFORE: {3}&Sort=LastUpdatedTime HighToLow";
requestBody = String.Format(requestBody, startPage, resultsPerPage, After.ToString("yyyy-MM-ddThh:mm:sszzz"),
Before.ToString("yyyy-MM-ddThh:mm:sszzz"));
HttpWebRequest httpWebRequest =
WebRequest.Create(dataServices.ServiceContext.BaseUrl + "bills/v2/" +
dataServices.ServiceContext.RealmId) as HttpWebRequest;
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
httpWebRequest.Headers.Add("Authorization", GetDevDefinedOAuthHeader(httpWebRequest, requestBody));
requestXML.Append(requestBody);
UTF8Encoding encoding = new UTF8Encoding();
byte[] content = encoding.GetBytes(requestXML.ToString());
using (var stream = httpWebRequest.GetRequestStream())
{
stream.Write(content, 0, content.Length);
}
HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
using (Stream data = httpWebResponse.GetResponseStream())
{
Intuit.Ipp.Data.Qbo.SearchResults searchResults =
(Intuit.Ipp.Data.Qbo.SearchResults)
dataServices.ServiceContext.Serializer.Deserialize<Intuit.Ipp.Data.Qbo.SearchResults>(
new StreamReader(data).ReadToEnd());
return ((Intuit.Ipp.Data.Qbo.Bills) searchResults.CdmCollections).Bill.ToList();
}
}
private string GetDevDefinedOAuthHeader(HttpWebRequest webRequest, string requestBody)
{
OAuthConsumerContext consumerContext = new OAuthConsumerContext
{
ConsumerKey = consumerKey,
ConsumerSecret = consumerSecret,
SignatureMethod = SignatureMethod.HmacSha1,
UseHeaderForOAuthParameters = true
};
consumerContext.UseHeaderForOAuthParameters = true;
OAuthSession oSession = new OAuthSession(consumerContext, "https://www.example.com",
"https://www.example.com",
"https://www.example.com");
oSession.AccessToken = new TokenBase
{
Token = accessToken,
ConsumerKey = consumerKey,
TokenSecret = accessTokenSecret
};
IConsumerRequest consumerRequest = oSession.Request();
consumerRequest = ConsumerRequestExtensions.ForMethod(consumerRequest, webRequest.Method);
consumerRequest = ConsumerRequestExtensions.ForUri(consumerRequest, webRequest.RequestUri);
if (webRequest.Headers.Count > 0)
{
ConsumerRequestExtensions.AlterContext(consumerRequest, context => context.Headers = webRequest.Headers);
if (webRequest.Headers[HttpRequestHeader.ContentType] == "application/x-www-form-urlencoded")
{
Dictionary<string, string> formParameters = new Dictionary<string, string>();
foreach (string formParameter in requestBody.Split('&'))
{
formParameters.Add(formParameter.Split('=')[0], formParameter.Split('=')[1]);
}
consumerRequest = consumerRequest.WithFormParameters(formParameters);
}
}
consumerRequest = consumerRequest.SignWithToken();
return consumerRequest.Context.GenerateOAuthParametersForHeader();
}

Resources