Read Http Request into Byte array - c#

I'm developing a web page that needs to take an HTTP Post Request and read it into a byte array for further processing. I'm kind of stuck on how to do this, and I'm stumped on what is the best way to accomplish. Here is my code so far:
public override void ProcessRequest(HttpContext curContext)
{
if (curContext != null)
{
int totalBytes = curContext.Request.TotalBytes;
string encoding = curContext.Request.ContentEncoding.ToString();
int reqLength = curContext.Request.ContentLength;
long inputLength = curContext.Request.InputStream.Length;
Stream str = curContext.Request.InputStream;
}
}
I'm checking the length of the request and its total bytes which equals 128. Now do I just need to use a Stream object to get it into byte[] format? Am I going in the right direction? Not sure how to proceed. Any advice would be great. I need to get the entire HTTP request into byte[] field.
Thanks!

The simplest way is to copy it to a MemoryStream - then call ToArray if you need to.
If you're using .NET 4, that's really easy:
MemoryStream ms = new MemoryStream();
curContext.Request.InputStream.CopyTo(ms);
// If you need it...
byte[] data = ms.ToArray();
EDIT: If you're not using .NET 4, you can create your own implementation of CopyTo. Here's a version which acts as an extension method:
public static void CopyTo(this Stream source, Stream destination)
{
// TODO: Argument validation
byte[] buffer = new byte[16384]; // For example...
int bytesRead;
while ((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0)
{
destination.Write(buffer, 0, bytesRead);
}
}

You can just use WebClient for that...
WebClient c = new WebClient();
byte [] responseData = c.DownloadData(..)
Where .. is the URL address for the data.

I use MemoryStream and Response.GetResponseStream().CopyTo(stream)
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url);
myRequest.Method = "GET";
WebResponse myResponse = myRequest.GetResponse();
MemoryStream ms = new MemoryStream();
myResponse.GetResponseStream().CopyTo(ms);
byte[] data = ms.ToArray();

I have a function that does it, by sending in the response stream:
private byte[] ReadFully(Stream input)
{
try
{
int bytesBuffer = 1024;
byte[] buffer = new byte[bytesBuffer];
using (MemoryStream ms = new MemoryStream())
{
int readBytes;
while ((readBytes = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, readBytes);
}
return ms.ToArray();
}
}
catch (Exception ex)
{
// Exception handling here: Response.Write("Ex.: " + ex.Message);
}
}
Since you have Stream str = curContext.Request.InputStream;, you could then just do:
byte[] bytes = ReadFully(str);
If you had done this:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(someUri);
req.Credentials = CredentialCache.DefaultCredentials;
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
You would call it this way:
byte[] bytes = ReadFully(resp.GetResponseStream());

class WebFetch
{
static void Main(string[] args)
{
// used to build entire input
StringBuilder sb = new StringBuilder();
// used on each read operation
byte[] buf = new byte[8192];
// prepare the web page we will be asking for
HttpWebRequest request = (HttpWebRequest)
WebRequest.Create(#"http://www.google.com/search?q=google");
// execute the request
HttpWebResponse response = (HttpWebResponse)
request.GetResponse();
// we will read data via the response stream
Stream resStream = response.GetResponseStream();
string tempString = null;
int count = 0;
do
{
// fill the buffer with data
count = resStream.Read(buf, 0, buf.Length);
// make sure we read some data
if (count != 0)
{
// translate from bytes to ASCII text
tempString = Encoding.ASCII.GetString(buf, 0, count);
// continue building the string
sb.Append(tempString);
}
}
while (count > 0); // any more data to read?
// print out page source
Console.WriteLine(sb.ToString());
Console.Read();
}
}

For all those cases when your context.Request.ContentLength is greather than zero, you can simply do:
byte[] contentBytes = context.Request.BinaryRead(context.Request.ContentLength);

Related

Web service File Stream to Byte[] to FileStream to pdf failing C#

I am trying to create a web service that returns a pdf file as a byte[] and then the app that consumes it grabs the byte[] and saves it as a pdf file and then opens it. The file fails to open at the end.
Here is the Web Service that returns a byte[]
[WebMethod]
public byte[] XXXX(int fileID)
{
try
{
using (EntitiesModel dbContext = new EntitiesModel())
{
string fileFullPath = .....
.......
if (fileFullNamePath != null)
{
FileStream fileStream = new FileStream(fileFullNamePath, FileMode.Open, System.IO.FileAccess.Read);
int len = fileStream.Length.ToInt();
Byte[] documentContents = new byte[len];
fileStream.Read(documentContents, 0, len);
fileStream.Close();
return documentContents;
Then it is called from an app with the following code
string soap = "<?xml version=\"1.0\" encoding=\"utf - 8\"?>" +
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
"<soap:Body>" +
"<XXXX xmlns=\"http://tempuri.org/\">" +
"<fileID>XXXXX</fileID>" +
"</XXXX>" +
"</soap:Body>" +
"</soap:Envelope>";
string localhostContext = #"http://localhost:3381/";
string webserviceAddress = #"XXXX/XXXX/XXXXX.asmx";
string url = localhostContext + webserviceAddress ;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = "text/xml";
request.ContentLength = soap.Length;
request.Timeout = 20000;
request.Method = "POST";
using (Stream stream = request.GetRequestStream())
{
using (StreamWriter streamWriter = new StreamWriter(stream))
{
streamWriter.Write(soap); }
}
}
byte[] bytes;
try
{
WebResponse response = request.GetResponse();
bytes = ReadFully(response.GetResponseStream());
}
catch (Exception exception)
{
throw;
}
private byte[] ReadFully(Stream input)
{
byte[] buffer = new byte[16*1024];
using (MemoryStream memoryStream = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
memoryStream.Position = 0;
memoryStream.Write(buffer, 0, read);
}
return memoryStream.ToArray();
}
}
FileStream objfilestream =
new FileStream(fileName, FileMode.Create,FileAccess.ReadWrite);
objfilestream.Write(bytes, 0, bytes.Length);
objfilestream.Close();
var process = Process.Start(fileName);
The code runs fine and creates a pdf and then tries to open that pdf. But the file can not be opened. Adobe Acrobat gives the error
Adobe Acrobat Reader could not open XXX.pdf because it is either not a
supported file type or because the file has been damaged (for example, it
was sent as an email attachment and wasn't correctly decoded).
Because I am not getting an error in the code I am at a loss to know where the error is that is not creating the proper file.
There was an issue with the Stream variable called input was not giving length so I used Jon Skeet's suggestion here Stackoverflow:Creating a byte array from a stream
new byte[16*1024];
rather than
new byte[input.length]
There were three things wrong.
memoryStream.Position = 0;
in the while loop was problematic so I removed it.
Secondly when reading the stream. What it returned was the SOAP XMl message with the encoded base64 string in the the XXXXResult XML tag. So I had to extract that.
Finally I had to use
byte[] fileResultBytes = Convert.FromBase64String(resultString);
to get the byte[] from the resultString extracted from the SOAP message. In the test SOAP message, that can be generated locally, it tells you the type of this result string. I missed that initially.
Thanks to VC.One and CodeCaster for their correct suggestions.

httpwebrespose does not receive pdf file?

A web application that receive and send a pdf file with signature. I send pdf file in httpwebrequest to the application. But not receive that pdf file with httpwebresponse ?
My code
byte[] pdfFile = File.ReadAllBytes("c:\\sample.pdf");
WebRequest request = WebRequest.Create("URL");
request.Credentials = new NetworkCredential("Username", "Password");
request.Proxy.Credentials = new NetworkCredential("Username", "Password");
request.Method = "POST";
request.ContentLength = pdfFile.Length;
request.ContentType = "application/pdf";
Stream stream = request.GetRequestStream();
stream.Write(pdfFile, 0, pdfFile.Length);
stream.Close();
WebResponse resp = request.GetResponse();
var buffer = new byte[4096];
MemoryStream memoryStream = new MemoryStream();
Stream responseStream =resp.GetResponseStream();
{
int count;
do
{
count = responseStream.Read(buffer, 0, buffer.Length);
memoryStream.Write
(buffer, 0, responseStream.Read(buffer, 0, buffer.Length));
} while (count != 0);
}
resp.Close();
byte[] memoryBuffer = memoryStream.ToArray();
System.IO.File.WriteAllBytes(#"c:\sample1.txt", memoryBuffer);
int s = memoryBuffer.Length;
BinaryWriter binaryWriter =
new BinaryWriter(File.Open(#"c:\sample2.txt", FileMode.Create));
binaryWriter.Write(memoryBuffer);
binaryWriter.Close();
//Read Fully is :
public static byte[] ReadFully(Stream input)
{
using (MemoryStream ms = new MemoryStream())
{
input.CopyTo(ms);
return ms.ToArray();
}
}
One problem you have is in your reading:
int count;
do
{
count = responseStream.Read(buffer, 0, buffer.Length);
memoryStream.Write(buffer, 0, responseStream.Read(buffer, 0, buffer.Length));
} while (count != 0);
You're reading the buffer twice each time through the loop. The bytes you read the first time are lost because you overwrite them. Your code should be:
int count;
do
{
count = responseStream.Read(buffer, 0, buffer.Length);
memoryStream.Write(buffer, 0, count);
} while (count != 0);
Also: I don't understand why you're writing the PDF to the request stream. Are you trying to send the PDF to a server and have it send the same file back?
What, exactly, are you trying to do here?

Download using c# code

I am developing c# application, in which i am downloading package(zip file) from server machine.It was downloading properly, but recently our package data has got some changes which is flex application.And by using c# we are downloading it into c drive or d drive.
Now with the new package i am facing some problem as
Unable to read data from the transport connection: An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full.
My code is below
byte[] packageData = null;
packageData = touchServerClient.DownloadFile("/packages/" + this.PackageName);
public byte[] DownloadFile(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(remoteSite.Url + url);
try
{
request.Method = "GET";
request.KeepAlive = false;
request.CookieContainer = new CookieContainer();
if (this.Cookies != null && this.Cookies.Count > 0)
request.CookieContainer.Add(this.Cookies);
HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse();
// Console.WriteLine(response.StatusDescription);
Stream responseStream = webResponse.GetResponseStream();
int contentLength = Convert.ToInt32(webResponse.ContentLength);
byte[] fileData = StreamToByteArray(responseStream, contentLength);
return fileData;
}
public static byte[] StreamToByteArray(Stream stream, int initialLength)
{
// If we've been passed an unhelpful initial length, just
// use 32K.
if (initialLength < 1)
{
initialLength = 32768;
}
byte[] buffer = new byte[initialLength];
int read = 0;
int chunk;
while ((chunk = stream.Read(buffer, read, buffer.Length - read)) > 0)
{
read += chunk;
// If we've reached the end of our buffer, check to see if there's
// any more information
if (read == buffer.Length)
{
int nextByte = stream.ReadByte();
// End of stream? If so, we're done
if (nextByte == -1)
{
return buffer;
}
// Nope. Resize the buffer, put in the byte we've just
// read, and continue
byte[] newBuffer = new byte[buffer.Length * 2];
Array.Copy(buffer, newBuffer, buffer.Length);
newBuffer[read] = (byte)nextByte;
buffer = newBuffer;
read++;
}
}
// Buffer is now too big. Shrink it.
byte[] ret = new byte[read];
Array.Copy(buffer, ret, read);
return ret;
}
In the above function(StreamToByteArray) , i am getting error as
Unable to read data from the transport connection: An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full.
Please help me on this, coz i am not supposed to change the code also.
Thanks in advance
Sangita
A few things to try:
Wrap your stream handling in a using statement.
This will clean up that resource.
using (Stream responseStream = webResponse.GetResponseStream())
{
int contentLength = Convert.ToInt32(webResponse.ContentLength);
byte[] fileData = StreamToByteArray(responseStream, contentLength);
return fileData;
}
Make sure there are no other heavy memory processes running on the same box. Particularly if they are making Socket-bound calls.
Try upping the value of the MaxUserPort registry value. Here is the article if you didn't see the link provided in the comments.

How to Serialise Images from Remote URL to IsolateStorage or to XML?

I need to download images from a remote URL and serialise them to Isolated Storage, but am having trouble with figuring out how to get this to work, I'm currently serialising the URIs to the Images - and can get this to work, but want to download the image and store it in the file system, what is the best way to do this using C# and Silverlight.
I've tried finding some ways to do this, but they are too complicated, if possible I can store Image Data in the XML if this is a solution, but I just want to download the file - .NET on the desktop has many methods to do this sort of thing, but I need a Silverlight Solution.
If there are any examples that demonstrate this sort of thing, then this may help too - it seems like a straightforward issue but I cannot resolve it and have tried many things to make this work simply, so that I can save an Image from a remote URL to IsolatedStorage and do this Asynchronously.
I do have some code that does this at the moment but I can't seem to streamline it, will post it if no suitable alternatives are posted if needed.
Try this class. I hope it'll help you.
To start grabbing use:
ImageGrabber grabber = new ImageGrabber();
grabber.GrabImage(#"http://www.google.com.ua/images/srpr/nav_logo25.png");
BTW in this example I've used very nice method which allow to read bytes from stream (even if this stream doesn't support Seek operation).
public class ImageGrabber
{
public void GrabImage(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.BeginGetRequestStream(RequestCallback, request);
}
private void RequestCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
request.BeginGetResponse(GetResponseCallback, request);
}
private void GetResponseCallback(IAsyncResult asynchronousResult)
{
HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;
// End the operation
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
byte[] bytes = ReadToEnd(streamResponse);
//save image to isolated storage as file.png
IsolatedStorageFile.GetUserStoreForApplication().CreateFile("file.png").Write(bytes, 0, bytes.Count());
}
private static byte[] ReadToEnd(Stream stream)
{
long originalPosition = stream.Position;
stream.Position = 0;
try
{
byte[] readBuffer = new byte[4096];
int totalBytesRead = 0;
int bytesRead;
while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0)
{
totalBytesRead += bytesRead;
if (totalBytesRead == readBuffer.Length)
{
int nextByte = stream.ReadByte();
if (nextByte != -1)
{
byte[] temp = new byte[readBuffer.Length * 2];
Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length);
Buffer.SetByte(temp, totalBytesRead, (byte)nextByte);
readBuffer = temp;
totalBytesRead++;
}
}
}
byte[] buffer = readBuffer;
if (readBuffer.Length != totalBytesRead)
{
buffer = new byte[totalBytesRead];
Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead);
}
return buffer;
}
finally
{
stream.Position = originalPosition;
}
}
}
File will be saved in isolated storage:
{System drive}:\Users\{User Name}\AppData\LocalLow\Microsoft\Silverlight\is\{bunch of autogenerated folders}\file.png
I've used the following:
WebClient client = new WebClient();
byte[] bytes = client.DownloadData("http://cdn.sstatic.net/stackoverflow/img/apple-touch-icon.png");

download online image asynchronously in .Net

I found the following example to download web page(string) asynchounously:
let getImage (imageUrl:string) =
async {
try
let req = WebRequest.Create(imageUrl) :?> HttpWebRequest
req.UserAgent <- "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)";
req.Method <- "GET";
req.AllowAutoRedirect <- true;
req.MaximumAutomaticRedirections <- 4;
let! response1 = req.AsyncGetResponse()
let response = response1 :?> HttpWebResponse
use stream = response.GetResponseStream()
use streamreader = new System.IO.StreamReader(stream)
return! streamreader.AsyncReadToEnd() // .ReadToEnd()
with
_ -> return "" // if there's any exception, just return an empty string
}
It returns a string. However, I need to download an online image(an array of bytes) asynchournously.
Anyone could give me some hint?
Maybe you can use my answer to another question (here). It asks the google chart API for an image (an URL) and converts the bytes to a Bitmap.
The relevant code:
async {
let req = HttpWebRequest.Create(..URI HERE..)
let! response = req.AsyncGetResponse()
return new Bitmap(response.GetResponseStream())
} |> Async.RunSynchronously
Use http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetresponse.aspx
Then you just GetResponseStream and read the bytes.
You can read the bytes directly from the stream. StreamReader works on strings. It actually inherits TextReader. Alternativly look at using a BinaryReader which works on bytes.
(Since you tagged it as C# I'll write my code sample in C#.)
Stream s = response.GetResponseStream()
MemoryStream memStream = new MemoryStream();
int bytesRead;
byte[] buffer = new byte[0x1000];
for (bytesRead = s.Read(buffer, 0, buffer.Length); bytesRead > 0; bytesRead = s.Read(buffer, 0, buffer.Length))
{
memStream.Write(buffer, 0, bytesRead);
}
s.Close();
return memStream.ToArray();
You can convert stream to array of bytes like this (C#)
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream(stream))
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
var bytes = ms.ToArray();
}

Categories