Sending Files in REST API via Apex - file-upload

I am integrating with one of the provider who accepts a file to upload in their system. While doing so they require the file to be sent as multipart/form-data in the following format !!
I tried configuring it as MultiPart form data using Base64 String still it is not working !!
-H "accept: application/json"
-H "x-api-key: API_KEY"
-H "x-api-token: API_TOKEN"
-H "Content-Type: multipart/form-data"
-F "file=#b4b35527-522d-4228-a266-bdaa80e28a8b.jpg;type=image/jpeg"

what you are looking for is not supported by the salesforce apex callout.
it's still in the salesforce Idea Exchange here is the link for the same.
https://trailblazer.salesforce.com/ideaView?id=08730000000Kr80AAC
You can vote for it but currently, multipart/form-data header is not supported.
please let me know if you have any questions.

Salesforce does support multipart/form-data but what it doesn't support is sending a Image as Blob.
For my requirement I needed to send the image / PDF / attachment as a form data. I used a slightly modified version of http://www.fishofprey.com/2017/04/steps-required-to-support-posting.html
I got another blob method to include the Images & Attachments as blob. Currently i have not added the codec for videos & other documents, but soon i will be adding those as the API does support that one.
Find here with teh modified version of HttpFormBuilder to include Images & Other Attachments as blob. We just need to add appropriate Codec.
public class HttpFormBuilder_Custom {
private final static string Boundary = '1ff13444ed8140c7a32fc4e6451aa76d';
public static string GetContentType() {
return 'multipart/form-data; charset="UTF-8"; boundary="' + Boundary + '"';
}
private static string SafelyPad(
string value,
string valueCrLf64,
string lineBreaks) {
string valueCrLf = '';
blob valueCrLfBlob = null;
while (valueCrLf64.endsWith('=')) {
value += ' ';
valueCrLf = value + lineBreaks;
valueCrLfBlob = blob.valueOf(valueCrLf);
valueCrLf64 = EncodingUtil.base64Encode(valueCrLfBlob);
}
return valueCrLf64;
}
public static string WriteBoundary() {
string value = '--' + Boundary + '\r\n';
blob valueBlob = blob.valueOf(value);
return EncodingUtil.base64Encode(valueBlob);
}
public static string WriteBoundary(
EndingType ending) {
string value = '';
if (ending == EndingType.Cr) {
value += '\n';
} else if (ending == EndingType.None) {
value += '\r\n';
}
value += '--' + Boundary + '--';
blob valueBlob = blob.valueOf(value);
return EncodingUtil.base64Encode(valueBlob);
}
/**
* Write a key-value pair to the form's body.
*/
public static string WriteBodyParameter(string key, string value) {
string contentDisposition = 'Content-Disposition: form-data; name="' + key + '"';
string contentDispositionCrLf = contentDisposition + '\r\n\r\n';
blob contentDispositionCrLfBlob = blob.valueOf(contentDispositionCrLf);
string contentDispositionCrLf64 = EncodingUtil.base64Encode(contentDispositionCrLfBlob);
string content = SafelyPad(contentDisposition, contentDispositionCrLf64, '\r\n\r\n');
string valueCrLf = value + '\r\n';
blob valueCrLfBlob = blob.valueOf(valueCrLf);
string valueCrLf64 = EncodingUtil.base64Encode(valueCrLfBlob);
content += SafelyPad(value, valueCrLf64, '\r\n');
return content;
}
/**
* Helper enum indicating how a file's base64 padding was replaced.
*/
public enum EndingType {
Cr,
CrLf,
None
}
public static string WriteBlobBodyParameter(string key, string file64, string fileName) {
String mimeType = resolveMimeType(fileName);
string contentDisposition = 'Content-Disposition: form-data; name="' + key + '"; filename="'+fileName+'"';
string contentDispositionCrLf = contentDisposition + '\r\n';
blob contentDispositionCrLfBlob = blob.valueOf(contentDispositionCrLf);
string contentDispositionCrLf64 = EncodingUtil.base64Encode(contentDispositionCrLfBlob);
string content = SafelyPad(contentDisposition, contentDispositionCrLf64, '\r\n');
string contentTypeHeader = 'Content-Type: ' + mimeType;
string contentTypeCrLf = contentTypeHeader + '\r\n\r\n';
blob contentTypeCrLfBlob = blob.valueOf(contentTypeCrLf);
string contentTypeCrLf64 = EncodingUtil.base64Encode(contentTypeCrLfBlob);
content += SafelyPad(contentTypeHeader, contentTypeCrLf64, '\r\n\r\n');
integer file64Length = file64.length();
String last4Bytes = file64.substring(file64.length()-4,file64.length());
// Avoid padding the file data with spaces, which SafelyPad does
// http://salesforce.stackexchange.com/a/33326/102
EndingType ending = EndingType.None;
if (last4Bytes.endsWith('==')) {
last4Bytes = last4Bytes.substring(0,2) + '0K';
file64 = file64.substring(0,file64.length()-4) + last4Bytes;
ending = EndingType.CrLf;
} else if (last4Bytes.endsWith('=')) {
last4Bytes = last4Bytes.substring(0,3) + 'N';
file64 = file64.substring(0,file64.length()-4) + last4Bytes;
ending = EndingType.Cr;
}
content += file64;
content += WriteBoundary(ending);
return content;
}
private static String resolveMimeType(String fileName) {
String fileType = fileName.substringAfterLast('.');
String mimeType = 'image/png'; // fallback value
if (fileType.equalsIgnoreCase('png')) {
mimeType = 'image/png';
} else if (fileType.equalsIgnoreCase('jpeg') || fileType.equalsIgnoreCase('jpg')) {
mimeType = 'image/jpg';
} else if (fileType.equalsIgnoreCase('pgm')) {
mimeType = 'image/x-portable-graymap';
} else if (fileType.equalsIgnoreCase('ppm')) {
mimeType = 'image/x-portable-pixmap';
}
return mimeType;
}
}

Related

Insert line breaks in VariableReplace in docx4j

I have been trying to fill up a word template(.docx) file which has placeholders which needs to be replaced.
I was able to rewrite the template but the text does not come with line breaks
I understand that carriage return or new line (\r\n) does not work in .docx files. I used the VariableReplace method to convert but I was unable to place br or factory.createBr() while using the variable replace.
Any suggestions would be really helpful. Below is the piece of code what i tried
Map<String,String> variableReplaceMap = new HashMap<>();
Map<String, String> textContent = readTextContentAfterDBExtractionToFillUpTemplate();
ObjectFactory factory = Context.getWmlObjectFactory();
P para = factory.createP();
R rspc = factory.createR();
String power= textContent.get("Power & Energy");
String[] powerWithNewLine = skills.split("\\\\n");
for (String eachLineOfPower : powerWithNewLine) {
Text eachLineOfPowerTxt = factory.createText();
eachLineOfPowerTxt .setValue( eachLineOfPower );
rspc.getContent().add( eachLineOfPowerTxt );
Br br = factory.createBr();
rspc.getContent().add(br);
para.getParagraphContent().add(rspc);
documentPart.addObject(para);
}
String str = "";
for (Object eachLineOfPgrph : para.getParagraphContent()) {
str = str + eachLineOfPgrph;
}
variableReplaceMap.put("POWER", str);
return variableReplaceMap;
The link from Jason is dead.
Here is the current link: https://github.com/plutext/docx4j/blob/master/docx4j-samples-docx4j/src/main/java/org/docx4j/samples/VariableReplace.java
In case it gets changed in the future, simply use the following function and apply it to your string, that contains linebreaks:
/**
* Hack to convert a new line character into w:br.
* If you need this sort of thing, consider using
* OpenDoPE content control data binding instead.
*
* #param r
* #return
*/
private static String newlineToBreakHack(String r) {
StringTokenizer st = new StringTokenizer(r, "\n\r\f"); // tokenize on the newline character, the carriage-return character, and the form-feed character
StringBuilder sb = new StringBuilder();
boolean firsttoken = true;
while (st.hasMoreTokens()) {
String line = (String) st.nextToken();
if (firsttoken) {
firsttoken = false;
} else {
sb.append("</w:t><w:br/><w:t>");
}
sb.append(line);
}
return sb.toString();
}
See newlineToBreakHack method at https://github.com/plutext/docx4j/blob/master/src/samples/docx4j/org/docx4j/samples/VariableReplace.java#L122

How to get list of email address based on a specified group (CN) from memberOf Attribute in Active Directory in java

I had written a program to fetch all attributes from active directory based on username. now i want to get list of email address based on the group name CN= App_abc_Admin inside memerOf attribute.
Main .java
public void ldapQueryService()throws Exception{
try {
System.out.println("Querying Active Directory Using Java");
System.out.println("------------------------------------");
String domain = "abc.com";
String url = "ldap.abc.com:389";
String username = "username";
String password = "password";
String choice = "samaccountname";
String searchTerm = "xyz";
//Creating instance of ActiveDirectory
ActiveDirectory activeDirectory = new ActiveDirectory(username, password, domain, url);
//Searching
NamingEnumeration<SearchResult> result = activeDirectory.searchUser(searchTerm, choice, null);
while (result.hasMore()) {
SearchResult rs = (SearchResult) result.next();
Attributes attrs = rs.getAttributes();
String temp = attrs.get("samaccountname").toString();
System.out.println("Username : " + temp.substring(temp.indexOf(":") + 1));
String memberOf = attrs.get("memberOf").toString();
String stringToSearch = "CN=App_abc_Admin";
boolean test = memberOf.toLowerCase().contains(stringToSearch.toLowerCase());
if(test){
String mail = attrs.get("mail").toString();
System.out.println("Email ID : " + mail.substring(mail.indexOf(":") + 1));
}
}
activeDirectory.closeLdapConnection();
}catch(Exception e){
}
}
ActiveDirectory.java
public class ActiveDirectory {
//required private variables
private Properties properties;
private DirContext dirContext;
private SearchControls searchCtls;
private String[] returnAttributes = { "*"};
private String domainBase;
private String baseFilter = "(&((&(objectCategory=Person)(objectClass=User)))";
public ActiveDirectory(String username, String password, String domainController,String url) {
properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
properties.put(Context.PROVIDER_URL, "LDAP://" + url);
properties.put(Context.SECURITY_PRINCIPAL, username + "#" + domainController);
properties.put(Context.SECURITY_CREDENTIALS, password);
//initializing active directory LDAP connection
try {
dirContext = new InitialDirContext(properties);
} catch (NamingException e) {
//LOG.severe(e.getMessage());
//e.printStackTrace();
}
//default domain base for search
domainBase = getDomainBase(domainController);
//initializing search controls
searchCtls = new SearchControls();
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
searchCtls.setReturningAttributes(returnAttributes);
}
public NamingEnumeration<SearchResult> searchUser(String searchValue, String searchBy, String searchBase) throws NamingException {
String filter = getFilter(searchValue, searchBy);
String base = (null == searchBase) ? domainBase : getDomainBase(searchBase);
return this.dirContext.search(base, filter, this.searchCtls);
}
public void closeLdapConnection(){
try {
if(dirContext != null)
dirContext.close();
}
catch (NamingException e) {
//e.printStackTrace();
}
}
private String getFilter(String searchValue, String searchBy) {
String filter = this.baseFilter;
if(searchBy.equals("email")) {
filter += "(mail=" + searchValue + "))";
} else if(searchBy.equals("username")) {
filter += "(samaccountname=" + searchValue + "))";
}else if(searchBy.equals("title")) {
filter += "(title=" + searchValue + "))";
}else if(searchBy.equals("department")) {
filter += "(department=" + searchValue + "))";
}else if(searchBy.equals("givenname")) {
filter += "(givenname=" + searchValue + "))";
}
else if(searchBy.equals("samaccountname")) {
filter += "(samaccountname=" + searchValue + "))";
}
return filter;
}
private static String getDomainBase(String base) {
char[] namePair = base.toUpperCase().toCharArray();
String dn = "DC=";
for (int i = 0; i < namePair.length; i++) {
if (namePair[i] == '.') {
dn += ",DC=" + namePair[++i];
} else {
dn += namePair[i];
}
}
return dn;
}
}
In the above example i'm passing the search by and search term. But how to get list of users based on the CN in the memberOf attribute?
I tried to update the filter as below but no output
private String baseFilter = "(&(objectClass=Person)(memberOf=cn=App_abc_Admin,ou=Application Groups,dc=abc,dc=com))";
updated the filter as below.It works now
private String baseFilter = "(&((&(objectCategory=Person)(objectClass=User)(mail=*abc.com)(memberOf=CN=App_abc_Admin,OU=Application Groups,OU=Security Groups,OU=Users_OU,DC=abc,DC=com))))";

How do I call Pay U Money Server through WCF?

i am creating a wcf service for Pay u Money I wrote same code like asp.net c# for Pay u Money, but using HttpWebRequest I'm facing this error:
SORRY! We were unable to process your payment
Same code I tried in simple asp.net c# and there working fine. Here I don't know what goes wrong, how could I solve this?
enter code here
public PayUMoneyModel PayUMoney(PayUMoneyModel Data)
{
PayUMoneyModel objPayUMoneyModel = new PayUMoneyModel();
action1 = ConfigurationManager.AppSettings["PAYU_BASE_URL"] +
"/_payment";
try
{
string[] hashVarsSeq;
string hash_string = string.Empty;
if (string.IsNullOrEmpty(Data.txnid)) // generating txnid
{
Random rnd = new Random();
string strHash = Generatehash512(rnd.ToString() +
DateTime.Now);
txnid1 = strHash.ToString().Substring(0, 20);
}
else if(Data.txnid!=null)
{
txnid1 = Data.txnid;
}
Data.txnid = txnid1;
Data.key= ConfigurationManager.AppSettings["MERCHANT_KEY"];
string salt= ConfigurationManager.AppSettings["SALT"];
System.Collections.Hashtable data = new System.Collections.Hashtable();
data.Add("key", Data.key);
data.Add("txnid", Data.txnid);
string AmountForm = Convert.ToDecimal(Data.amount).ToString("g29");// eliminating trailing zeros
//amount.Text = AmountForm;
data.Add("amount", 1.00);
data.Add("firstname", Data.firstname);
data.Add("email", Data.email);
data.Add("phone", Data.phone);
data.Add("productinfo", Data.productinfo);
data.Add("surl", Data.surl);
data.Add("furl", Data.furl);
data.Add("lastname", Data.lastname);
data.Add("curl", Data.curl);
data.Add("address1", Data.address1);
data.Add("address2", Data.address2);
data.Add("city", Data.city);
data.Add("state", Data.state);
data.Add("country",Data.country);
data.Add("zipcode", Data.zipcode);
data.Add("udf1", Data.udf1);
data.Add("udf2", Data.udf2);
data.Add("udf3", Data.udf3);
data.Add("udf4", Data.udf4);
data.Add("udf5", Data.udf5);
data.Add("pg", Data.pg);
data.Add("service_provider", "payu_paisa");
hash_string = Data.key + "|" + Data.txnid + "|" + AmountForm + "|" + Data.productinfo+ "|" + Data.firstname + "|" + Data.email + "|||||||||||" + salt;
string hash = Generatehash512(hash_string);
data.Add("hash", hash);
data.Add("abc", hash_string);
string strForm = PreparePOSTForm(action1, data);
if (strForm != "")
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create(action1);
// httpWebRequest.ContentType = "text/html";
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
httpWebRequest.Method = "POST";
httpWebRequest.ContentLength = strForm.Length;
string Json = "";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(strForm,0,strForm.Length);
streamWriter.Flush();
streamWriter.Close();
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
Json = streamReader.ReadToEnd().Replace(";", "");
}
}
HttpContext.Current.Response.Write(Json);
}
}
catch(Exception ex)
{
throw ex;
}
return objPayUMoneyModel;
}
this is my Post Form Method
private string PreparePOSTForm(string url, System.Collections.Hashtable data) // post form
{
//Set a name for the form
string formID = "PostForm";
//Build the form using the specified data to be posted.
StringBuilder strForm = new StringBuilder();
strForm.Append("<form id=\"" + formID + "\" name=\"" +
formID + "\" action=\"" + url +
"\" method=\"POST\">");
foreach (System.Collections.DictionaryEntry key in data)
{
strForm.Append("<input type=\"hidden\" name=\"" + key.Key +
"\" value=\"" + key.Value + "\">");
}
strForm.Append("</form>");
//Build the JavaScript which will do the Posting operation.
StringBuilder strScript = new StringBuilder();
strScript.Append("<script language='javascript'>");
strScript.Append("var v" + formID + " = document." +
formID + ";");
strScript.Append("v" + formID + ".submit();");
strScript.Append("</script>");
//Return the form and the script concatenated.
//(The order is important, Form then JavaScript)
return strForm.ToString() + strScript.ToString();
}
this is my key and salt provided by Payumoney website:-
Key:-rjQUPktU
Salt:-e5iIg1jwi8

using AE.Net.Mail how to send mail with image inline

I using AE.Net.Mail in .net project.
I sent html mail and file attachment by gmail api and it work perfect.
But i dont know way to embed an image in body mail with it?
Somebody help me ?
string To = txtTo.Text;
string Subject = txtEmailSubject.Text;
string Body = hdfEmailContentSend.Value;
string InputAttachmentArr = hdfInputAttachmentArr.Value;
var msg = new AE.Net.Mail.MailMessage();
msg.From = new MailAddress("haunguyen1791990#gmail.com", "=?UTF-8?B?" + EncodeTo64UTF8(User.FullName) + "?=");
msg.ReplyTo.Add(msg.From);
msg.To.Add(new MailAddress(To));
msg.Subject = "=?UTF-8?B?" + EncodeTo64UTF8(Subject) + "?=";
msg.Body = Body;
var result = SendMessage(InputAttachmentArr, msg, "");
private Google.Apis.Gmail.v1.Data.Message SendMessage(string InputAttachmentArr, AE.Net.Mail.MailMessage msg, string ThreadId) {
try {
bool isAttackFile = false;
string boundary = "boundary_" + DateTime.Now.ToString("yyyyMMddHHmmss");
var service = CRMGmailUtils.DefineServiceGet(Server.MapPath(".") + "\\client_secret.json");
//get info file attachment
List<string> lstAttachFile = InputAttachmentArr.Split(',').ToList();
lstAttachFile.RemoveAll(item => item.Length == 0);
foreach (var item in lstAttachFile) {
string filePath = Server.MapPath("~/" + "Upload/gmail/" + item);
var bytes = File.ReadAllBytes(filePath);
AE.Net.Mail.Attachment file = new AE.Net.Mail.Attachment(bytes, GetMimeType(item), item, true);
msg.Attachments.Add(file);
isAttackFile = true;
}
var msgStr = new StringWriter();
//if file attachment not exists, set type mail is html
if (!isAttackFile) {
msg.ContentType = "text/html";
}
msg.Save(msgStr);
string data = msgStr.ToString();
//else i customize body mail with new boundary
if (isAttackFile) {
string beginBody = "Content-Type: multipart/alternative; boundary=" + boundary;
//beginBody += "\n\n--" + boundary;
//beginBody += "\nContent-Type: text/plain; charset=UTF-8";
//beginBody += "\n\n*2*";
beginBody += "\n\n--" + boundary;
beginBody += "\nContent-Type: text/html; charset=UTF-8";
string endBody = "\n\n--" + boundary + "--";
msg.Body += endBody;
string parentBoundary = Regex.Match(data, #"----(.*?)--").Groups[1].Value;
Regex rgx = new Regex("----" + parentBoundary);
data = rgx.Replace(data, "----" + parentBoundary + "\n" + beginBody, 1);
}
string raw = Base64UrlEncode(data.ToString());
var result = new Google.Apis.Gmail.v1.Data.Message();
//case send with reply
if (!string.IsNullOrEmpty(ThreadId)) {
result = service.Users.Messages.Send(new Google.Apis.Gmail.v1.Data.Message { Raw = raw, ThreadId = ThreadId }, "me").Execute();
} else {
//case send new mail
result = service.Users.Messages.Send(new Google.Apis.Gmail.v1.Data.Message { Raw = raw }, "me").Execute();
}
DeleteAttackFile(lstAttachFile);
return result;
} catch (Exception objEx) {
throw objEx;
}
}

NameValueCollection in Windows Phone 8

I want to use NameValueCollection in windows phone 8, but I can not see this option in WP8 SDK. Can you help me please?
This function has been removed.
But a query can be manipulated using parsing and a SortedDictionary. i.e. This snippet sorts a query string:
public string sortQuery(string myUrl)
{
string url = myUrl.Substring(0, myUrl.IndexOf("?") + 1);
string q = myUrl.Substring(myUrl.IndexOf("?") + 1);
string[] pr = q.Split('&');
SortedDictionary<string,string> d = new SortedDictionary<string,string>();
foreach (string s in pr)
{
string[] prm = s.Split('=');
string key = prm[0];
string value = "";
if (prm.Length > 1) { value = "=" + prm[1]; }
d.Add(key, value);
}
string result = "";
foreach (var k in d.Keys)
{
result += k + d[k] + "&";
}
result = result.Substring(0, result.Length - 1);
return url + result;
}