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
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
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);
}
}
}
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"
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
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>