How to read HttpResponseContent as Stream using system.net.http - c#

I have a piece of code to read HttpResponseContent using windows.web.http:
using System.IO;
using Windows.Web.Http;
using Newtonsoft.Json;
var responseContent = JsonConvert.DeserializeObject<HttpResponseContent>(response.Content.ToString());
if (response.StatusCode == HttpStatusCode.Ok)
{
//convert only from this line
using (var input =
await response.Content.ReadAsInputStreamAsync()
.AsTask()
.ConfigureAwait(false))
using (var stream = input.AsStreamForRead())
using (StreamReader sr = new StreamReader(stream))
using (JsonReader reader = new JsonTextReader(sr)) //to this line
{
return DeserializeData(reader);
}
Question 1: How can I achieve this using system.net.http namespace?
Note: I wrote those codes in uwp using windows.web.http, what I want is to convert that code using different package/namespace, which is system.net.http which I am using in Azure Functions.
Reference Link: https://learn.microsoft.com/en-us/dotnet/api/system.net.http?view=netframework-4.7.2 https://learn.microsoft.com/en-us/uwp/api/windows.web.http
Thanks

using (var input =
await response.Content.ReadAsStreamAsync()
.ConfigureAwait(false))
using (StreamReader sr = new StreamReader(input))
using (JsonReader reader = new JsonTextReader(sr))
{
return DeserializeData(reader);
}

Related

Better way to process large HttpClient response (400mb) to ZipArchive

I will try to keep it short and precise.
Requirement:
Download large (400mb) xml response from 3rd party and store as ZipArchive on disk.
Current solution:
using (var memoryStream = new MemoryStream())
{
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
var file = archive.CreateEntry($"{deliveryDate:yyyyMMdd}.xml");
using(var entryStream = file.Open())
{
using (var payload = new MemoryStream())
{
using var response = await _httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
response.EnsureSuccessStatusCode();
await response.Content.CopyToAsync(payload);
payload.Seek(0, SeekOrigin.Begin);
await payload.CopyToAsync(entryStream);
}
}
}
using (var fileStream = new FileStream(Path.Combine(filePath), FileMode.Create, FileAccess.Write, FileShare.None))
{
memoryStream.Seek(0, SeekOrigin.Begin);
await memoryStream.CopyToAsync(fileStream);
}
}
Additional Information:
I can compress a 400mb file to approx. 20mb in about 40 seconds. 1/4 is download 3/4 is compression.
The httpClient is re-used.
The code runs in a long lived application hosted as a k8 linux pod.
Issues with current solution:
I fail to understand if this implementation will clean up after itself. I would be thankful for pointers towards potential leaks.
may be writing more directly to the filestream would be faster / cleaner
and the response should be disposed:
using System.IO.Compression;
string url = "https://stackoverflow.com/questions/70605408/better-way-to-process-large-httpclient-response-400mb-to-ziparchive";
string filePath = "test.zip";
using(HttpClient client = new HttpClient())
using (var fileStream = new FileStream(Path.Combine(filePath), FileMode.Create, FileAccess.Write, FileShare.None))
using (var archive = new ZipArchive(fileStream, ZipArchiveMode.Create, true))
{
var file = archive.CreateEntry($"test.xml");
using (var entryStream = file.Open())
using (var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
{
response.EnsureSuccessStatusCode();
var stream = await response.Content.ReadAsStreamAsync();
await stream.CopyToAsync(entryStream);
}
}

C# unzip and read file from HttpWebResponse

I'm trying to unzip and read file from HttpWebResponse object with followed code:
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
using (MemoryStream ms = new MemoryStream())
{
response.GetResponseStream().CopyTo(ms);
ms.Seek(0, SeekOrigin.Begin);
using (ZipArchive za = new ZipArchive(ms, ZipArchiveMode.Read))
{
foreach (ZipArchiveEntry zae in za.Entries)
{
using (StreamReader sr = new StreamReader(zae.Open(), Encoding.GetEncoding(1251), true, 2 << 18))
{
Console.WriteLine(sr.ReadLine());
}
}
}
}
but getting System.IO.InvalidDataException: End of Central Directory record could not be found.
What i'm doing wrong?
Here is kind of what I was thinking with GZipStream (just an example, no guarantees here)...
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
using (GZipStream gzipStream = new GZipStream(response.GetResponseStream(), CompressionMode.Decompress))
using (StreamReader sr = new StreamReader(gzipStream))
{
Console.Write(sr.ReadToEnd());
}

Google speech to text API using C#

I'm using google speech recognition for speech to text of a audio file. Response i get as output shows only {"result":[]}. I don't see any output result.
i have picked my code from How to use google speech recognition api in c#? and Google speech to text API in C# . i have tried almost every answer in above links still i am getting the error.
My code is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.IO;
using Newtonsoft.Json;
namespace google_api
{
class Program
{
static void Main(string[] args)
{
try
{
FileStream fileStream = File.OpenRead("good-morning-google.flac");
MemoryStream memoryStream = new MemoryStream();
memoryStream.SetLength(fileStream.Length);
fileStream.Read(memoryStream.GetBuffer(), 0, (int)fileStream.Length);
byte[] BA_AudioFile = memoryStream.GetBuffer();
HttpWebRequest _HWR_SpeechToText = null;
_HWR_SpeechToText =
(HttpWebRequest)HttpWebRequest.Create(
"https://www.google.com/speech-api/v2/recognize?output=json&lang=en-us&key=mykey");
_HWR_SpeechToText.Credentials = CredentialCache.DefaultCredentials;
_HWR_SpeechToText.Method = "POST";
_HWR_SpeechToText.ContentType = "audio/x-flac; rate=44100";
_HWR_SpeechToText.ContentLength = BA_AudioFile.Length;
Stream stream = _HWR_SpeechToText.GetRequestStream();
stream.Write(BA_AudioFile, 0, BA_AudioFile.Length);
stream.Close();
HttpWebResponse HWR_Response = (HttpWebResponse)_HWR_SpeechToText.GetResponse();
if (HWR_Response.StatusCode == HttpStatusCode.OK)
{
StreamReader SR_Response = new StreamReader(HWR_Response.GetResponseStream());
Console.WriteLine(SR_Response.ReadToEnd()+SR_Response.ToString());
string responseFromServer = (SR_Response.ReadToEnd());
String[] jsons = responseFromServer.Split('\n');
String text = "";
foreach (String j in jsons)
{
dynamic jsonObject = JsonConvert.DeserializeObject(j);
if (jsonObject == null || jsonObject.result.Count <= 0)
{
continue;
}
text = jsonObject.result[0].alternative[0].transcript;
}
Console.WriteLine("MESSAGE : "+text);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.ReadLine();
}
}
}

Modify a printTicket

I'm trying to modify a print ticket since many days. :(
Here is the code :
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Printing;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Drawing.Printing;
using System.Drawing;
using System.Xml;
// ....
// Get the ticket
var printQueue = new PrintServer("\\\\NetworkNameHere").GetPrintQueue("PrinterNameHere");
PrintTicket userPrintTicket = printQueue.UserPrintTicket;
// Modify the ticket to print in landscape (or any other option)
var xmlDoc = new XmlDocument();
xmlDoc.Load(userPrintTicket.GetXmlStream());
var manager = new XmlNamespaceManager(xmlDoc.NameTable);
manager.AddNamespace(xmlDoc.DocumentElement.Prefix, xmlDoc.DocumentElement.NamespaceURI);
string xpath = string.Format("//psf:Feature[#name='{0}']/psf:Option", "psk:PageOrientation");
XmlNode node = xmlDoc.SelectSingleNode(xpath, manager);
node.Attributes["name"].Value = "psk:Landscape";
PrintTicket modifiedPrintTicket = null;
using (var stream = new MemoryStream())
{
xmlDoc.Save(stream);
stream.Position = 0;
modifiedPrintTicket = new PrintTicket(stream);
}
System.Printing.ValidationResult result = printQueue.MergeAndValidatePrintTicket(printQueue.UserPrintTicket, modifiedPrintTicket);
printQueue.UserPrintTicket = result.ValidatedPrintTicket;
MessageBox.Show(result.ValidatedPrintTicket.PageOrientation.Value.ToString());
printQueue.Commit();
Byte[] myByteBuffer = UnicodeEncoding.Unicode.GetBytes("This is a test string for the print job stream.");
using (var job = printQueue.AddJob())
using (var stream = job.JobStream)
{
stream.Write(myByteBuffer, 0, myByteBuffer.Length);
stream.Close();
}
The problem :
Look like the ticket is correctly modified, but for some reasons it never use the information specified in the ticket for any option. HELP!!!!
Note that I'm using .Net 4.0 but I get the same result with the new PrintTicket parameter in addJob (4.5) : printQueue.AddJob("xx", result.ValidatedPrintTicket)
Thanks!

Download blob storage and return Json object

I am trying to download a .json blob that I have stored in a container in the Azure Storage using Newtonsoft.Json to write it to an object.
I am doing this by calling:
(CloudBlockBlob) blob.DownloadToStream(stream);
However, instead of writing the stream to a file in the local app directory, I want to return the json object doing Json(result)
This is what I have tried:
using (var stream = new MemoryStream())
{
blob.DownloadToStream(stream);
var serializer = new JsonSerializer();
using (var sr = new StreamReader(stream))
{
using (var jsonTextReader = new JsonTextReader(sr))
{
result = serializer.Deserialize(jsonTextReader);
}
}
}
At the end my jsonTextReader variable is empty and the object null
What can I do to accomplish this?
Thank you
Both the question and accepted answer start by copying the entire stream into a MemoryStream which is effectively a big byte array in memory. This step is unnecessary - it's more memory-efficient to stream the blob data directly to the object without buffering the bytes first:
using (var stream = await blob.OpenReadAsync())
using (var sr = new StreamReader(stream))
using (var jr = new JsonTextReader(sr))
{
result = JsonSerializer.CreateDefault().Deserialize<T>(jr);
}
Please reset the stream's position to 0 after reading the blob into the stream. So your code would be:
using (var stream = new MemoryStream())
{
blob.DownloadToStream(stream);
stream.Position = 0;//resetting stream's position to 0
var serializer = new JsonSerializer();
using (var sr = new StreamReader(stream))
{
using (var jsonTextReader = new JsonTextReader(sr))
{
var result = serializer.Deserialize(jsonTextReader);
}
}
}
In case you don't care for streaming and want a short and concise way:
var json = await blockBlob.DownloadTextAsync();
var myObject = JsonConvert.DeserializeObject<MyObject>(json);

Categories

Resources