My outlook plugin sends large files over https. Currently I'm using Convert.ToBase64String() on the client side and Convert.FromBase64String() on the http handler on the IIS Side.
This has come to some performance issues, and also i'm also securing the data over SSL so i'm really asking if there's any way to convert a byte array over https without using encoding that will cost cpu performance on the recipient end.
My Client code:
string requestURL = "http://192.168.1.46/websvc/transfer.trn";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestURL);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
// Chunk(buffer) is converted to Base64 string that will be convert to Bytes on the handler.
string requestParameters = #"fileName=" + fileName + #"&secretKey=testKey=" + #"¤tChunk=" + i + #"&totalChunks=" + totalChunks + #"&smGuid=" + smGuid +
"&data=" + HttpUtility.UrlEncode(Convert.ToBase64String(bytes));
// finally whole request will be converted to bytes that will be transferred to HttpHandler
byte[] byteData = Encoding.UTF8.GetBytes(requestParameters);
request.ContentLength = byteData.Length;
Stream writer = request.GetRequestStream();
writer.Write(byteData, 0, byteData.Length);
writer.Close();
// here we will receive the response from HttpHandler
StreamReader stIn = new StreamReader(request.GetResponse().GetResponseStream());
string strResponse = stIn.ReadToEnd();
stIn.Close();
Server code where I have performance issues:
byte[] buffer = Convert.FromBase64String(context.Request.Form["data"]); //
You don't have to send using contentType application/x-www-form-urlencoded. Why not just set as something like application/octet-stream, set a content length and copy your data right into the request stream? As long as you interpret it correctly at the other end, you'll be fine.
If you use WCF Data Services, you can send binary data via a separate binary stream
[Data can be sent] as a separate binary resource stream. This is the recommended method for accessing and changing binary large object (BLOB) data that may represent a photo, video, or any other type of binary encoded data.
http://msdn.microsoft.com/en-us/library/ee473426.aspx
You can also upload binary data using HttpWebRequest
Passing binary data through HttpWebRequest
Upload files with HTTPWebrequest (multipart/form-data)
Related
how would I be able to do something like http://myanimelist.net/modules.php?go=api#verifycred
aka "curl -u user:password http://myanimelist.net/api/account/verify_credentials.xml"
I wish to option the id
my code so far is
string url = "http://myanimelist.net/api/account/verify_credentials.xml";
WebRequest request = WebRequest.Create(url);
request.ContentType = "xml";
request.Method = "GET";
request.Credentials = new NetworkCredential(username, password);
byte[] buffer = Encoding.GetEncoding("UTF-8").GetBytes("xml/user/id"); // i think this line?
Stream reqstr = request.GetRequestStream();
reqstr.Write(buffer, 0, buffer.Length);
reqstr.Close();
but I get a error on "reqstr.Write(buffer, 0, buffer.Length)"
Cannot send a content-body with this verb-type, I have tried googling but with no prevail, I am using c#
Your snippet is trying to send a GET request with request data (you're calling GetRequestStream and then writing some data to the request stream). The HTTP protocol does not allow this - you can only send data with POST request.
However, the API that you are trying to call is actually doing something different - you do not need to send it the XML data. The XML data (with user ID and user name) is the response that you get when you successfully login.
So, instead of calling GetRequestStream and writing the XML data, you need to call GetResponse and then GetResponseStream to read the XML data!
I have the following code that uploads the file to the server by making the POST request:
string fileName = #"C:\Console_sk.txt";
HttpWebRequest request = (HttpWebRequest) HttpWebRequest.Create("http://" + Environment.MachineName + ":8000/Upload");
request.Method = "POST";
request.ContentType = "text/plain";
request.AllowWriteStreamBuffering = false;
Stream fileStream = new FileStream(fileName, FileMode.Open);
request.ContentLength = fileStream.Length;
Stream serverStream = request.GetRequestStream();
byte[] buffer = new byte[4096];
while (true)
{
int bytesRead = fileStream.Read(buffer, 0, buffer.Length);
if (bytesRead > 0)
{
serverStream.Write(buffer, 0, bytesRead);
}
else
{
break;
}
}
serverStream.Close();
fileStream.Close();
request.GetResponse();
This will be used to upload potentially large files, therefore it is essential for us to track the progress of this upload.
Based on various sources, I've thought that my code will upload file in 4096 byte chunks i.e. multiple POST requests will be made. But when tracking requests by using Fiddler, it shows that only one POST request is made. On other hand, when I enabled .NET network tracing, the resulting log showed that 4096 byte chunks are indeed written to request stream and the socket is always being opened for each write operation.
My understanding of networking in general is quite poor, so I don't quite understand how this really works. When calling serverStream.Write, is the provided chunk really sent over the network, or is it just buffered somewhere? And when serverStream.Close is called, can I be sure that the whole file has been uploaded?
The HttpWebRequest class sends a single HTTP request. What you are doing is that you are writing to the request in chunks to avoid loading the whole file in memory. You are reading from the file and directly writing to the request stream in chunks of 4KB.
When calling serverStream.Write, is the provided chunk really sent over the network
Yes, it is written to the network socket.
I need to post data to a website. So I created a small app in C#.net where I open this website and fill in all the controls (radio buttons, text boxes, checkboxes etc) with the values from my database. I also have a click event on the SUBMIT button. The app then waits for 10-15 seconds and then copies the response from the webpage to my database.
As you can see, this is really a hectic process. If there are thousands of records to upload, this app takes much longer (due to fact that it waits 15s for the response).
Is there any other way to post data? I am looking for something like concatenating all the fields with its value and uploading it like a stream of data. How will this work if the website is https and not http?
You can use HttpWebRequest to do this, and you can concatenate all the values you want to post into a single string for the request. It could look something like this:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://www.yoursite.com");
request.Method = "POST";
formContent = "FormValue1=" + someValue +
"&FormValue2=" + someValue2 +
"&FormValue=" + someValue2;
byte[] byteArray = Encoding.UTF8.GetBytes(formContent);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
WebResponse response = request.GetResponse();
dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = HttpUtility.UrlDecode(reader.ReadToEnd());
//You may need HttpUtility.HtmlDecode depending on the response
reader.Close();
dataStream.Close();
response.Close();
This method should work fine for http and https.
MSDN has a great article with step-by-step instructions detailing how you can use the WebRequest class to send data. Link below:
http://msdn.microsoft.com/en-us/library/debx8sh9.aspx
Yes, there is a WebClient class. Look into documentation. There're some usful method to make GET and POST requests.
I read documentation of Salesforce Chatter REST API and started to implement code in c#.
See following code:
System.Net.WebRequest req = System.Net.WebRequest.Create(URI);
req.Method = "POST";
req.Headers.Add("Authorization: OAuth " + accessToken);
req.ContentType = "application/x-www-form-urlencoded";
string par =
"fileName=" + fileName +
"&feedItemFileUpload="
+ #"D:\\MyFiles\\NewTextDocument.txt" +
"&desc=" + desc+
"&text=" + text;
byte[] byteArray = Encoding.UTF8.GetBytes(par);
req.ContentLength = byteArray.Length;
Stream dataStream = req.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
System.Net.WebResponse resp = req.GetResponse();
I am gettig error on response
The remote server returned an error: (400) Bad Request.
If i see response of error, i got following message:
Please specify a file to upload. Type in the path to the file, or use the \"Browse\" button to locate it in your local filesystem.
I have already defined the file path and name. I tried with and without # sign before path string but getting same error. Let me know if anything is missing.
You can easily use Fiddler to see what's going on.
You are posting a simple form where fileName and feedItemFileUpload are just like desc and text, in other words, plain simple text!
What you need to do is send the file as a stream.
I can see that you're using Hanselman's code, but that's only for text parameters
for more information on using it for files, see this answer
Upload files with HTTPWebrequest (multipart/form-data)
I found this snippet of code here that allows you to log into a website and get the response from the logged in page. However, I'm having trouble understanding all the part of the code. I've tried my best to fill in whatever I understand so far. Hope you guys can fill in the blanks for me. Thanks
string nick = "mrbean";
string password = "12345";
//this is the query data that is getting posted by the website.
//the query parameters 'nick' and 'password' must match the
//name of the form you're trying to log into. you can find the input names
//by using firebug and inspecting the text field
string postData = "nick=" + nick + "&password=" + password;
// this puts the postData in a byte Array with a specific encoding
//Why must the data be in a byte array?
byte[] data = Encoding.ASCII.GetBytes(postData);
// this basically creates the login page of the site you want to log into
WebRequest request = WebRequest.Create("http://www.mrbeanandme.com/login/");
// im guessing these parameters need to be set but i dont why?
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
// this opens a stream for writing the post variables.
// im not sure what a stream class does. need to do some reading into this.
Stream stream = request.GetRequestStream();
// you write the postData to the website and then close the connection?
stream.Write(data, 0, data.Length);
stream.Close();
// this receives the response after the log in
WebResponse response = request.GetResponse();
stream = response.GetResponseStream();
// i guess you need a stream reader to read a stream?
StreamReader sr = new StreamReader(stream);
// this outputs the code to console and terminates the program
Console.WriteLine(sr.ReadToEnd());
Console.ReadLine();
A Stream is a sequence of bytes.
In order to use text with a Stream, you need to convert it into a sequence of bytes.
This can be done manually with the Encoding classes or automatically with StreamReader and StreamWriter. (which read and write strings to streams)
As stated in the documentation for GetRequestStream,
You must call the Stream.Close method to close the stream and release the connection for reuse. Failure to close the stream causes your application to run out of connections.
The Method and Content-* properties reflect the underlying HTTP protocol.