Read URL request to string C# console aplication - c#

I am trying to read url request that was sent via browser to my server. So basicly if I type http://localhost:8080/geoserver/ as my URL, server will respond and send a picture that is going to be displayed properly. Now I am trying to get the URL into string so if for example I type http://localhost:8080/geoserver/1234 I would be able to get 1234 out of my url string and then resize, rotate,.. my picture based on the input and display it. I tried with string my_url = listen.GetContext().toString(); but I am not getting URL that I've entered.
My code:
static void Main(string[] args)
{
HttpListener listen = new HttpListener();
string url = "http://localhost";
string port = "";
Console.Write("Nastavite port:");
port = Console.ReadLine();
url = url + ":" + port + "/geoserver/";
listen.Prefixes.Add(url);
try
{
listen.Start();
}
catch(Exception e)
{
Console.WriteLine("Ta port je zaseden");
Console.ReadKey();
Environment.Exit(0);
}
while (true)
{
Console.WriteLine("Cakam...");
HttpListenerContext kontekst = listen.GetContext();
string msg = "hello world";
// kontekst.Response.ContentLength64 = Encoding.UTF8.GetByteCount(msg);
kontekst.Response.StatusCode = (int)HttpStatusCode.OK;
using (Stream stream = kontekst.Response.OutputStream)
using (Image image = Image.FromFile("jpg.png"))
using (MemoryStream ms = new MemoryStream())
using (StreamWriter writer = new StreamWriter(stream))
{
image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
string base64 = Convert.ToBase64String(ms.ToArray());
writer.WriteLine($"<html><img src=\"data: image / png; base64, {base64} \"></html>");
}
Console.WriteLine("Sporočilo poslano");
}
}

You need to get the URI from kontekst.Request.Url and parse out that value yourself to decide what you need to do.

Related

Cannot read data from HttpListener .NET

I am stuck with reading data from HttpListener. Data arrives, I verify it with request.ContentLength64 that is usually over 8000 and it increases as the server generates more and more data.
The server sends data as HTTP post and the content type is text/plain.
When I try to check whether streamreader got some data via its length attribute I get 0.
The code is a little bit messy as I was trying different ways to make it work but unfortunatelly I had no luck.
Does anyone got an idea what I'm doing wrong?
Thanks!
HttpListener listener2 = new HttpListener();
listener2.Prefixes.Clear();
listener2.Prefixes.Add("http://+:4200/");
listener2.Prefixes.Add("http://XXX.XXX.eu/");
listener2.Start();
LogWriteLine("http listener started listening to: " +listener2.Prefixes);
try
{
while (true)//change to match end check
{
LogWriteLine("http listener waiting");
HttpListenerContext context = listener2.GetContext();
LogWriteLine("http request arrived");
HttpListenerRequest request = context.Request;
// Obtain a response object.
HttpListenerResponse response = context.Response;
System.IO.Stream body = request.InputStream;
System.Text.Encoding encoding = request.ContentEncoding;
System.IO.StreamReader reader = new System.IO.StreamReader(body, encoding);
if (!request.HasEntityBody)
{
LogWriteLine("No client data was sent with the request.");
Thread.Sleep(300);
//return;
}
if (request.ContentType != null)
{
LogWriteLine("Client data content type " + request.ContentType);
}
LogWriteLine("Client data content length " + request.ContentLength64); //Works fine
LogWriteLine("Start of client data:");
// Convert the data to a string and display it on the console.
Console.WriteLine(body.CanSeek);
string s = reader.ReadToEnd();
var ahoj = new StreamReader(context.Request.InputStream).ReadToEnd();
Console.WriteLine("ahoj length " + ahoj.Length); //0
Console.WriteLine(s); //nothing
string text;
var bytes = default(byte[]);
using (var reader1 = new StreamReader(request.InputStream,
request.ContentEncoding))
{
text = reader1.ReadToEnd();
Console.WriteLine(text + text.Length); //output: 0
using (var memstream = new MemoryStream())
{
reader1.BaseStream.CopyTo(memstream);
bytes = memstream.ToArray();
}
Console.WriteLine("bytes:" + bytes.Length); //output: bytes: 0
}
LogWriteLine("End of client data:");
//write to console file
sw.Write(s);
body.Close();
reader.Close();
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}

Convert API, new API version docx to PDF

I'm using Convert API to convert docx to PDF. With the old API version everything works good, but I'm trying to migrate to the new API version and when I open the PDF is not a valid document and it will not open. Not sure what I am doing wrong, maybe something about the encoding?
The response that I get from Convert API is a JSON with the File Name, File Size and File Data. Maybe this File Data needs to be processed to create a valid PDF file? if I just write that data in a file it does not work.
public string ConvertReportToPDF(string fileName)
{
string resultFileName = "";
key = "xxxxx";
var requestContent = new MultipartFormDataContent();
var fileStream = System.IO.File.OpenRead(fileName);
var stream = new StreamContent(fileStream);
requestContent.Add(stream, "File", fileStream.Name);
var response = new HttpClient().PostAsync("https://v2.convertapi.com/docx/to/pdf?Secret=" + key, requestContent).Result;
FileReportResponse responseDeserialized = JsonConvert.DeserializeObject<FileReportResponse>(response.Content.ReadAsStringAsync().Result);
var path = SERVER_TEMP_PATH + "\\" + responseDeserialized.Files.First().FileName;
System.IO.File.WriteAllText(path, responseDeserialized.Files.First().FileData);
return responseDeserialized.Files.First().FileName;
}
File data in JSON is Base64 encoded, decode it before writing to a file.
public string ConvertReportToPDF(string fileName)
{
string resultFileName = "";
key = "xxxxx";
var requestContent = new MultipartFormDataContent();
var fileStream = System.IO.File.OpenRead(fileName);
var stream = new StreamContent(fileStream);
requestContent.Add(stream, "File", fileStream.Name);
var response = new HttpClient().PostAsync("https://v2.convertapi.com/docx/to/pdf?Secret=" + key, requestContent).Result;
FileReportResponse responseDeserialized = JsonConvert.DeserializeObject<FileReportResponse>(response.Content.ReadAsStringAsync().Result);
var path = SERVER_TEMP_PATH + "\\" + responseDeserialized.Files.First().FileName;
System.IO.File.WriteAllText(path, Convert.FromBase64String(responseDeserialized.Files.First().FileData));
return responseDeserialized.Files.First().FileName;
}
Why to use JSON response in C# when you can use binary response instead. A response will be smaller, no need to decode. To change response type you need to add accept=application/octet-stream header to request to ask for binary response from server. The whole code will look like
using System;
using System.Net;
using System.IO;
class MainClass {
public static void Main (string[] args) {
const string fileToConvert = "test.docx";
const string fileToSave = "test.pdf";
const string Secret="";
if (string.IsNullOrEmpty(Secret))
Console.WriteLine("The secret is missing, get one for free at https://www.convertapi.com/a");
else
try
{
Console.WriteLine("Please wait, converting!");
using (var client = new WebClient())
{
client.Headers.Add("accept", "application/octet-stream");
var resultFile = client.UploadFile(new Uri("http://v2.convertapi.com/docx/to/pdf?Secret=" + Secret), fileToConvert);
File.WriteAllBytes(fileToSave, resultFile );
Console.WriteLine("File converted successfully");
}
}
catch (WebException e)
{
Console.WriteLine("Status Code : {0}", ((HttpWebResponse)e.Response).StatusCode);
Console.WriteLine("Status Description : {0}", ((HttpWebResponse)e.Response).StatusDescription);
Console.WriteLine("Body : {0}", new StreamReader(e.Response.GetResponseStream()).ReadToEnd());
}
}
}

How to go to start of Stream to avoid two webrequests?

I have a small C# console app working that copies the results of a webrequest to a text file and then runs each command in that text file, saving the results to a separate text file.
Problem is, I have to make two requests to the same server, which I don't like doing. The problem is I can't seem to go to the beginning of the Stream/StreamReader after writing it to the text file, forcing me to make another request.
How do I do this with only one webrequest?
Thanks,
John
static void Main(string[] args)
{
// Set all variables
string epoUrl = "https://de-ser2012ecm:8443/remote/core.help.do";
string commandHelpPath = #"C:\Logs\AllCommandsHelp.txt";
string coreHelpPath = #"C:\Logs\CoreHelp.txt";
string epoUsername = "admin";
string epoPassword = "password";
string responseFromServer;
StringReader strReader;
try
{
// Get stream from webrequest
Stream coreStream = WebHelper.GetWebResponseStream(epoUrl, epoUsername, epoPassword);
StreamReader coreReader = new StreamReader(coreStream);
// Write core help page to text file
using (StreamWriter corefile = new StreamWriter(coreHelpPath, true, Encoding.UTF8))
{
responseFromServer = coreReader.ReadToEnd();
// Display the content.
corefile.Write(responseFromServer);
strReader = new StringReader(responseFromServer);
}
// Get new stream from webrequest
Stream commandStream = WebHelper.GetWebResponseStream(epoUrl, epoUsername, epoPassword);
StreamReader commandReader = new StreamReader(commandStream);
using (StreamWriter outfile = new StreamWriter(commandHelpPath, true, Encoding.UTF8))
{
while (!strReader.Peek().Equals(-1))
{
string streamLine = strReader.ReadLine();
string[] words = streamLine.Split(' ');
// Check if first string contains a period that's not at the end
if ((words[0].Contains(".")) & !(words[0].EndsWith(".")))
{
StreamReader helpReader = WebHelper.GetWebResponse(epoUrl + "?command=" + words[0], epoUsername, epoPassword);
string helpResponseFromServer = helpReader.ReadToEnd();
outfile.Write(helpResponseFromServer);
outfile.WriteLine("==============================");
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("Main exception: " + ex.Message);
}
finally
{
// Close streams
//coreReader.Close();
//commandReader.Close();
Console.WriteLine("Press any key to continue");
Console.ReadKey();
}
}
And the GetWebResponseStream method:
public static Stream GetWebResponseStream(string url, string username, string password)
{
Stream dataStream = null;
try
{
// Set the credentials.
CredentialCache credentialCache = new CredentialCache();
credentialCache.Add(new System.Uri(url), "Basic", new System.Net.NetworkCredential(username, password));
ServicePointManager.ServerCertificateValidationCallback = (s, cert, chain, ssl) => true;
// Create a request for the URL.
WebRequest request = WebRequest.Create(url);
request.Credentials = credentialCache;
// Get the response.
WebResponse response = request.GetResponse();
// Get the stream containing content returned by the server.
dataStream = response.GetResponseStream();
return dataStream;
}
catch (Exception ex)
{
Console.WriteLine("GetWebResponse threw an exception: " + ex.Message);
return dataStream;
}
}
Thanks to Gildor for the suggestion that put me on the right track. I had the response, I just needed to copy that string into a StringReader. This automatically resets the cursor so you can read from the top! I updated the code to show the new fix. Thanks to everyone for the suggestions. John

c# Web Server - How to send images

I'm creating a server using C# and I'm able to receive requests and return HTML, but I'm not sure what I have to do to send image files so they will display on the page.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.IO;
namespace Ambar
{
class Program
{
static void Main(string[] args)
{
TcpListener listener = new TcpListener(80);
listener.Start();
while (true)
{
Console.WriteLine("waiting for a connection");
TcpClient client = listener.AcceptTcpClient();
StreamReader sr = new StreamReader(client.GetStream());
StreamWriter sw = new StreamWriter(client.GetStream());
Console.WriteLine(client.GetStream().ToString());
try
{
string request = sr.ReadLine();
Console.WriteLine(request);
string[] tokens = request.Split(' ');
string page = tokens[1];
if (page == "/")
{
page = "/default.htm";
}
StreamReader file = new StreamReader("../../web" + page);
sw.WriteLine("HTTP/1.0 200 OK\n");
string data = file.ReadLine();
while (data != null)
{
sw.WriteLine(data);
sw.Flush();
data = file.ReadLine();
}
}
catch (Exception e)
{
sw.WriteLine("HTTP/1.0 404 OK\n");
sw.WriteLine("<H1> Future Site of Ambar Remake </H!>");
sw.Flush();
}
client.Close();
}
}
}
I'm able to host whatever HTML I want, but if I try to display an image like
<img src="picture.gif" alt="a picture" height="42" width="42">
I'm not sure how to host that image and have it displayed there.
I assume you are using web sockets.
You'll need to return the image as a base 64 encoded string, then use the
<img src ="data:image/png;base64," + base64ImageHere
Format
HTTP request and response header have two line breaks(\n) to divide Header part and content part.
for example:
(Request that requesting an image(image.gif) from server)
GET /image.gif HTTP/1.1
User-Agent: WebBrowser
Accept-Encoding: deflate,gzip
Connection: keep-alive
... and more headers if present ...
(Response for image request)
HTTP/1.1 200 OK
Content-Length: <Length_Of_Content>
Content-Type: image/gif
... and more headers if present ...
<Data_Of_Image>
As you can see, there's two line breaks(\n) between response header and contents.
So, you have to read files as byte array(byte[]). In this situation, you can easily read files using System.IO.File.ReadAllBytes(string).
Now, one more left. I told you read files as byte array, but there's no way to join string and byte[]. So you have to encode string to byte[] and join header bytes and content bytes.
+ We can't send byte array via StreamWriter so, we'll use NetworkStream.
Here's explanation:
NetworkStream ns = client.GetStream();
...
string[] tokens = request.Split(' ');
string page = tokens[1];
if (page == "/")
{
page = "/default.htm";
}
//StreamReader file = new StreamReader("../../web" + page);
byte[] file = null;
try { file = File.ReadAllBytes(#"../../web" + page); }
// In this 'catch' block, you can't read requested file.
catch {
// do something (like printing error message)
}
// We are not going to use StreamWriter, we'll use StringBuilder
StringBuilder sbHeader = new StringBuilder();
// STATUS CODE
sbHeader.AppendLine("HTTP/1.1 200 OK");
// CONTENT-LENGTH
sbHeader.AppendLine("Content-Length: " + file.Length);
// Append one more line breaks to seperate header and content.
sbHeader.AppendLine();
// List for join two byte arrays.
List<byte> response = new List<byte>();
// First, add header.
response.AddRange(Encoding.ASCII.GetBytes(sbHeader.ToString()));
// Last, add content.
response.AddRange(file);
// Make byte array from List<byte>
byte[] responseByte = response.ToArray();
// Send entire response via NetworkStream
ns.Write(responseByte, 0, responseByte.Length);
This is it. I hope you can understand my bad english :O.
Hope this help to you!

Upload file with webrequest

Im trying to upload an image to an imagehost http://uploads.im/.
According to its very short API http://uploads.im/apidocs this is a way of doing that:
http://uploads.im/api?upload=http://www.google.com/images/srpr/nav_logo66.png
Note that in this example he is upploading an image from the internet and Im trying to upload a file from my computer.
Code:
public ActionResult SaveUploadedFile()
{
//Converts the image i want to upload to a bytearray
Image postData = img;
byte[] byteArray = imageToByteArray(postData);
//Is this adress not correct maybe? Is there a way to test?
WebRequest wrq = WebRequest.Create("http://uploads.im/api?upload=");
wrq.Method = ("POST");
//Im thinking that here I need som code
//that specifys the file i want to upload (bytearray)
using (WebResponse wrs = wrq.GetResponse())
using (Stream stream = wrs.GetResponseStream())
using (StreamReader reader = new StreamReader(stream))
{
string json = reader.ReadToEnd();
tempJson = json;
}
}
Please have look! Thanks!
EDIT, new code:
string filepath = #"c:\Users\xxxx\Desktop\Bilder\images\blank.gif";
using (WebClient client = new WebClient())
{
client.UploadFile("http://uploads.im/api?upload", filepath);
}
I get the error: : The underlying connection closed
EDIT with try catch:
string filepath = #"c:\Users\xxxx\Desktop\sack.png";
using (WebClient client = new WebClient())
{
try
{
client.UploadFile("http://uploads.im/api?upload", filepath);
}
catch (Exception e)
{
throw new ApplicationException(e);
}
}
private void UploadImage(string filepath)
{
using(WebClient uploader = new WebClient())
{
try
{
uploader.UploadFile(new Uri("http://uploads.im/api?upload"), filepath);
}
catch(Exception ex)
{
MessageBox.Show("An error occured :(\r\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
I'm using http://uploads.im/api?upload as the Endpoint, because, as read in the docs, it will be treated as REQUEST and will automatically detect the upload of an image.
However, I tried this code myself and get disconnected every-time without any meaningful response, just The remote host unexpectedly closed the connection. According to the docs you should get a Bad request when something is wrong. I contacted the support and hope they can tell me more about it. (Edit: They did not)

Categories