HttpWebRequest works. WebClient.UploadFile doesn't - wcf

I thought I figured out a way to simplify my code by using WebClient.UploadFile instead of HttpWebRequest, but I end up getting a file on the server end that is a few dozen bytes too short and corrupted. Any idea where the bug lies?
Thanks
Using HttpWebRequest (works fine):
HttpWebRequest req = (HttpWebRequest)HttpWebRequest
.Create("http://" +
ConnectionManager.FileServerAddress + ":" +
ConnectionManager.FileServerPort +
"/binary/up/" + category + "/" +
Path.GetFileName(filename) + "/" + safehash);
req.Method = "POST";
req.ContentType = "binary/octet-stream";
req.AllowWriteStreamBuffering = false;
req.ContentLength = bytes.Length;
Stream reqStream = req.GetRequestStream();
int offset = 0;
while (offset < ____)
{
reqStream.Write(bytes, offset, _________);
_______
_______
_______
}
reqStream.Close();
try
{
HttpWebResponse resp = (HttpWebResponse) req.GetResponse();
}
catch (Exception e)
{
_____________
}
return safehash;
Using WebClient (corrupt file on server end):
var client = new WebClient();
client.Encoding = Encoding.UTF8;
client.Headers.Add(HttpRequestHeader.ContentType, "binary/octet-stream");
client.UploadFile(new Uri("http://" +
ConnectionManager.FileServerAddress + ":" +
ConnectionManager.FileServerPort +
"/binary/up/" + category + "/" +
Path.GetFileName(filename) + "/" + safehash), filename);
return safehash;
Server side is a WCF service:
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "up/file/{fileName}/{hash}")]
void FileUpload(string fileName, string hash, Stream fileStream);

WebClient.UploadFile sends the data in a multipart/form-data format. What you want to use to have the equivalent to the code using HttpWebRequest is the WebClient.UploadData method:
var client = new WebClient();
client.Encoding = Encoding.UTF8;
client.Headers[HttpRequestHeader.ContentType] = "application/octet-stream";
byte[] fileContents = File.ReadAllBytes(filename);
client.UploadData(new Uri("http://" + ConnectionManager.FileServerAddress + ":" +
ConnectionManager.FileServerPort +
"/binary/up/" + category + "/" +
Path.GetFileName(filename) + "/" + safehash), fileContents);

Related

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

AtTask / Workfront API File Upload

I'm write a generic upload so I can upload items via the API but not having much success. Getting either a 500 unauthorized or 400 bad request. Here's my attempt after a bit of googling. Not sure if this is over complicated. Have also tried a cut down approach. There's a few posts but none that actually work or are confirmed as working. I'll post a simplified version later and I'm aware this will not return a value. Just trying to get passed the exception before I refine.
public JToken DoUpload(string path, string file, params string[] parameters)
{
string result = string.Empty;
if (!path.StartsWith("/"))
{
path = "/" + path;
}
string fullUrl = url + path;// +ToQueryString(parameters);
string contentType = "multipart/form-data";
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
wr.ContentType = "multipart/form-data; boundary=" + boundary;
wr.Method = "POST";
//wr.Headers.Add("sessionID","XXXXXXXXXXXXXX"); NEEDED?
Stream rs = wr.GetRequestStream();
rs.Write(boundarybytes, 0, boundarybytes.Length);
string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string formitem = string.Format(formdataTemplate, "uploadedFile", "temp.jpg", contentType);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
rs.Write(formitembytes, 0, formitembytes.Length);
rs.Write(boundarybytes, 0, boundarybytes.Length);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, "uploadedFile", "temp.jpg", contentType);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length);
FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
rs.Write(buffer, 0, bytesRead);
}
fileStream.Close();
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
rs.Write(trailer, 0, trailer.Length);
rs.Close();
WebResponse wresp = null;
Stream stream2;
StreamReader reader2;
try
{
wresp = wr.GetResponse();
stream2 = wresp.GetResponseStream();
reader2 = new StreamReader(stream2);
}
catch (Exception ex)
{
if (wresp != null)
{
wresp.Close();
wresp = null;
}
}
finally
{
wr = null;
}
return result;
}
Figured out a simpler solution if helps anyone:
public JToken DoUpload(string path, string file, string sessionID){
if (!path.StartsWith("/")){
path = "/" + path;
}
string fullUrl = url + path;
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
HttpWebRequest webrequest = (HttpWebRequest)WebRequest.Create(fullUrl);
webrequest.ContentType = "multipart/form-data; boundary=" + boundary;
webrequest.Method = "POST";
webrequest.Accept = "application/json;charset=UTF-8";
webrequest.Headers.Add("sessionID", sessionID);
// Build up the post message header
StringBuilder sb = new StringBuilder();
sb.Append("--");
sb.Append(boundary);
sb.Append("\r\n");
sb.Append("Content-Disposition: form-data; name=\"");
sb.Append("uploadedFile");
sb.Append("\"; filename=\"");
sb.Append(Path.GetFileName(file));
sb.Append("\"");
sb.Append("\r\n");
sb.Append("Content-Type: ");
sb.Append("application/octet-stream");
sb.Append("\r\n");
sb.Append("\r\n");
string postHeader = sb.ToString();
byte[] postHeaderBytes = Encoding.UTF8.GetBytes(postHeader);
// Build the trailing boundary string as a byte array
// ensuring the boundary appears on a line by itself
byte[] boundaryBytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
FileStream fileStream = new FileStream(file,FileMode.Open, FileAccess.Read);
long length = postHeaderBytes.Length + fileStream.Length + boundaryBytes.Length;
webrequest.ContentLength = length;
Stream requestStream = webrequest.GetRequestStream();
// Write out our post header
requestStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);
// Write out the file contents
byte[] buffer = new Byte[checked((uint)Math.Min(4096, (int)fileStream.Length))];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
requestStream.Write(buffer, 0, bytesRead);
}
// Write out the trailing boundary
requestStream.Write(boundaryBytes, 0, boundaryBytes.Length);
using (WebResponse response = webrequest.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
return ReadResponse(responseStream);
}
}
}

how to utf-8 encode the file name with uploading the file content in multi part post

Having uploading file working fine except when the file name is double byte.
The code snippet below shows a possible place to do the file name encoding, but not sure if it is right, or where is the right place to apply "charset=utf-8". Any help is appreciated.
HttpURLConnection connection = null;
DataOutputStream outputStream = null;
DataInputStream inputStream = null;
String urlString = WebApiConstants.getInstance().getBaseURL();
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "--BoundaryStringUsingCurrentTime”+currentTimeMillis();
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
try {
URL url = new URL(urlString);
connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
List<BasicNameValuePair> headers = getHeaderNameValuePairs();
for (BasicNameValuePair hdr : headers) {
connection.setRequestProperty(hdr.getName(), hdr.getValue());
}
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.writeBytes(twoHyphens + boundary + lineEnd);
outputStream.writeBytes("Content-Disposition: form-data; name=\"requests\"" + lineEnd);
outputStream.writeBytes("Content-Type: application/json" + lineEnd + lineEnd);
outputStream.writeBytes(getJsonDataString(attachment.getMessageId()));
outputStream.writeBytes(lineEnd + twoHyphens + boundary + lineEnd);
/* ???
// could encode the fail name and put in, not sure if it is right?
String fileNameUtf8 = URLEncoder.encode(fileName, "UTF-8");
outputStream.writeBytes("Content-Disposition: form-data; name=\"file0\";filename=\""
+ fileNameUtf8 + "\"" + lineEnd);
*/
outputStream.writeBytes("Content-Disposition: form-data; name=\"file0\";filename=\""
+ fileName + "\"" + lineEnd);
outputStream.writeBytes("Content-Type: " + mimeType + lineEnd + lineEnd);
FileInputStream fileInputStream = new FileInputStream(new File(pathToFile));
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, MAX_BUFFER_SIZE);
buffer = new byte[bufferSize];
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
outputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, MAX_BUFFER_SIZE);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
outputStream.writeBytes(lineEnd);
outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
… … …
… … …
You can encode the filename like this:
final private static String hexStr = "0123456789ABCDEF";
private static String MimeEncodeQP(String s)
{
byte[] bytes = s.getBytes("UTF-8");
StringBuilder output = new StringBuilder(12 + (bytes.length * 3));
output.append("=?UTF-8?Q?");
for ( final byte b : bytes )
{
if( b == 32 )
{
output.append('_');
}
else if( ((b >= 33) && (b <= 60)) ||
((b >= 62) && (b <= 126)) )
{
output.append((char) b);
}
else
{
output.append('=')
.append(hexStr.charAt((b & 0xF0) >> 4)
.append(hexStr.charAt(b & 0x0F));
}
}
output.append("?=");
return output.toString();
}
outputStream.writeBytes("Content-Disposition: form-data; name=\"file0\";filename=\"" + MimeEncodeQP(fileName) + "\"" + lineEnd);
Read the following specs for more details:
RFC 2045 "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies", Section 67 "Quoted-Printable Content-Transfer-Encoding"
RFC 2047 "MIME (Multipurpose Internet Mail Extensions) Part Three: Message Header Extensions for Non-ASCII Text"
RFC 7578 "Returning Values from Forms: multipart/form-data", Section 5.1 "Non-ASCII Field Names and Values".
HTML4, Section 17.13.4.2 "multipart/form-data"
HTML5, Section 4.10.22.7 "Multipart form data"

Invalid signature error with UpgradeableApp API

I am trying to run a code that would allow me to migrate Google Apps Marketplace to upgrade my apps to use OAuth 2.0 authentication for subscribed domains.
Unfortunately, I receive the following error message:
{"error":{"errors":[{"domain":"global","reason":"authError","message":"Invalid OAuth signature","locationType":"header","location":"Authorization"}],"code":401,"message":"Invalid OAuth signature"}}
The code that I run is:
final String consumerKey = "xxx";
final String consumerSecret = "yyy";
final String domain = "example.com";
final String account = "admin#example.com";
OAuthParameters oauthParameters = new OAuthParameters();
oauthParameters.setOAuthConsumerKey(consumerKey);
oauthParameters.setOAuthConsumerSecret(consumerSecret);
OAuthHmacSha1Signer signer = new OAuthHmacSha1Signer();
final String marketPlaceListingId = "xxxx+xxxxxxxxxxxxxxxxxxx";
final String chromeWebStoreItemId = "yyyyyyyyyyyyyyyyyyyyyyyyyyyy";
String requestUrl = "https://www.googleapis.com/appsmarket/v2/upgradableApp/"
+ marketPlaceListingId + "/" + chromeWebStoreItemId + "/" + domain;
String oauth_nonce = OAuthUtil.getNonce();
String oauth_timestamp = OAuthUtil.getTimestamp().toString();
String signatureMethod = "HMAC-SHA1";
oauthParameters.setOAuthType(OAuthType.TWO_LEGGED_OAUTH);
oauthParameters.setOAuthNonce(oauth_nonce);
oauthParameters.setOAuthTimestamp(oauth_timestamp);
oauthParameters.setOAuthSignatureMethod(signatureMethod);
String baseString = "PUT"
+ "&" + OAuthUtil.encode(requestUrl)
+ "&" + OAuthUtil.encode("oauth_consumer_key=" + oauthParameters.getOAuthConsumerKey()
+ "&oauth_nonce=" + oauth_nonce
+ "&oauth_signature_method=" + signatureMethod
+ "&oauth_timestamp=" + oauth_timestamp
+ "&oauth_version=1.0"
+ "&xoauth_requestor_id=" + OAuthUtil.encode(account));
String oauth_signature = signer.getSignature(baseString, oauthParameters);
oauthParameters.setOAuthSignature(oauth_signature);
OAuthHelper oauthHelper = new GoogleOAuthHelper(signer);
String header = oauthHelper.getAuthorizationHeader(requestUrl + "?xoauth_requestor_id=" + OAuthUtil.encode(account), "PUT", oauthParameters);
HttpClient httpClient = new DefaultHttpClient();
HttpPut httpPut = new HttpPut(requestUrl + "?xoauth_requestor_id=" + OAuthUtil.encode(account));
httpPut.addHeader("Authorization", header);
//httpPut.addHeader("Content-Type", "application/x-www-form-urlencoded");
HttpResponse response = null;
try {
response = httpClient.execute(httpPut);
} catch (Exception e) {
System.out.println(e.getMessage());
throw new ServletException(e);
}
Please support.
Thank you,
Evgeny

REST Update Recipient Email using PUT Method

I am new to REST and keep getting the Bad Request 400 Response with the code below:
I have the standard baseURL and authenticateStr from the other sample...
_recipientID, pNewEmail, pNewName and pNewRoutingOrder are passed in as parameters to the procedures.
string envDef = "<envelopeDefinition xmlns=\"http://www.docusign.com/restapi\">" +
"<signers>" +
"<signer>" +
"<recipientId>" + _recipientId + "</recipientId>" +
"<email>" + pNewEmail + "</email>" +
"<name>" + pNewName + "</name>" +
"<routingOrder>" + pNewRoutingOrder + "</routingOrder>" +
"</signer>" +
"</signers>" +
"</envelopeDefinition>";
url = baseURL + "/envelopes/" + pEnvelopeID + "/recipients";
request = (HttpWebRequest)WebRequest.Create(url);
request.Headers.Add("X-DocuSign-Authentication", authenticateStr);
request.ContentType = "application/xml";
request.Accept = "application/xml";
request.ContentLength = envDef.Length;
request.Method = "PUT";
// write the body of the request
byte[] body = System.Text.Encoding.UTF8.GetBytes(envDef);
Stream dataStream = request.GetRequestStream();
dataStream.Write(body, 0, envDef.Length);
dataStream.Close();
// read the response
webResponse = (HttpWebResponse)request.GetResponse();
sr.Close();
responseText = "";
sr = new StreamReader(webResponse.GetResponseStream());
responseText = sr.ReadToEnd();
Ok just figured out how to do this. Here's an XML request body that can be used to update the email and name of a recipient, for instance. I just verified that this works!
<recipients xmlns="http://www.docusign.com/restapi">
<signers>
<signer>
<recipientId>1</recipientId>
<email>email#docusign.com</email>
<name>Joe Mama</name>
</signer>
</signers>
</recipients>