How to clone the random access stream? - xamarin.forms

I want to clone the IRandomAccessStream. I tried the CloneStream() to clone the stream but it not supported. Is there any way to clone the random access stream.
Thanks,
Santhiya A

You can use the CopyTo method
https://learn.microsoft.com/en-us/dotnet/api/system.io.stream.copyto?view=netframework-4.7.2

You can try converting it to a byte[] and then clone the byte[] in to new IRandomAccessStream.
public async Task<IRandomAccessStream> CloneIRandomeAccessStream(IRandomAccessStream randomAccessStream)
{
var reader = new DataReader(randomAccessStream.GetInputStreamAt(0));
byte[] bytes = new byte[randomAccessStream.Size];
await reader.LoadAsync((uint)randomAccessStream.Size);
reader.ReadBytes(bytes);
MemoryStream stream = new MemoryStream(bytes.ToArray());
IRandomAccessStream ClonerandomAccessStream = stream.AsRandomAccessStream();
return ClonerandomAccessStream;
}

Related

Aspose.Words Returning PDF as Stream does nothing (ASP.NET Web API)

We are exploring using Aspose.Words for some conversions in an on premise API.
This works perfectly for Excel sheets using Aspose.Cells.
[HttpPost]
[Route("convert/excel")]
public async Task<IActionResult> ConvertExcel(IFormFile fileToConvert)
{
var fileStream = new MemoryStream();
fileToConvert.CopyTo(fileStream);
var convertedFile = await pdfConverter.ConvertExcelAsync(fileStream);
return File(convertedFile, "application/octet-stream");
}
However when using exactly the same method for Aspose.Words it does nothing, literally nothing just continues for a few minutes and then times out. This is not a timeout issue with the conversion as the file is 200KB.
[HttpPost]
[Route("convert/word")]
public async Task<IActionResult> ConvertWord(IFormFile fileToConvert)
{
var fileStream = new MemoryStream();
fileToConvert.CopyTo(fileStream);
var convertedFile = await pdfConverter.ConvertWordAsync(fileStream);
return File(convertedFile, "application/octet-stream");
}
I have tried various forms of returning a file but no luck.
return new FileStreamResult(convertedFile, "application/pdf");
The actual conversion methods look like this.
public Task<Stream> ConvertWordAsync(Stream fileStream)
{
return Task.Factory.StartNew(() => ConvertWord(fileStream));
}
private Stream ConvertWord(Stream inputFile)
{
var doc = new Document(inputFile);
var outputFile = new MemoryStream();
doc.Save(outputFile, Aspose.Words.SaveFormat.Pdf);
//doc.Save(#"C:\ProgramData\foo.pdf", Aspose.Words.SaveFormat.Pdf); //THIS WORKS BUT NOT APPOPRIATE
return outputFile;
}
I have also updated it to support HttpGet and hard-coded a path to a file and in browser just get a Download failed - network error.
Is is possible that the Save method returns the memory stream at the end of the stream.
You should try the following immediately after the call to doc.Save
outputFile.Seek(0, SeekOrigin.Begin);

Zip Azure Storage Files and Return File from Web Api

I am trying to create a zip file with SharpZipLib from files stored on Azure Storage. Unfortunately I am not able to return them because the Api always returns a Json:
{"Version":{"Major":1,"Minor":1,"Build":-1,"Revision":-1,"MajorRevision":-1,"MinorRevision":-1},"Content":{"Headers":[{"Key":"Content-Disposition","Value":["attachment; filename=Documents.zip"]},{"Key":"Content-Type","Value":["application/octet-stream"]},{"Key":"Content-Length","Value":["498"]}]},"StatusCode":200,"ReasonPhrase":"OK","Headers":[],"RequestMessage":null,"IsSuccessStatusCode":true}
The zipping should work which I use, however I am not sure if everything is correct since I was never able to see the file.
This is the code for zipping the files and returning the zip file:
[HttpGet("DownloadFiles")]
public async Task<HttpResponseMessage> DownloadFiles(string invoiceNr, List<string> fileNames)
{
List<CloudBlockBlob> blobs = _documentService.GetBlobs(invoiceNr, fileNames);
MemoryStream outputMemStream = new MemoryStream();
ZipOutputStream zipStream = new ZipOutputStream(outputMemStream);
zipStream.SetLevel(3); //0-9, 9 being the highest level of compression
foreach (CloudBlockBlob blob in blobs)
{
using (MemoryStream blobStream = new MemoryStream())
{
await blob.DownloadToStreamAsync(blobStream);
ZipEntry newEntry = new ZipEntry(blob.Name);
newEntry.DateTime = DateTime.Now;
zipStream.PutNextEntry(newEntry);
StreamUtils.Copy(blobStream, zipStream, new byte[4096]);
zipStream.CloseEntry();
}
}
zipStream.IsStreamOwner = false; // False stops the Close also Closing the underlying stream.
zipStream.Close(); // Must finish the ZipOutputStream before using outputMemStream.
outputMemStream.Position = 0;
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new StreamContent(outputMemStream);
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = "Documents.zip";
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentLength = outputMemStream.Length;
return result;
}
Is it the wrong way of returning a file from WebAPi? Am I doing something wrong in general?
Thanks in advance for the help.
As you declare your web method as
public async Task<HttpResponseMessage> DownloadFiles(...)
ASP.NET Core treats HttpResponseMessage as model and your methods returns instance of this file serialized as JSON.
The correct version of this method is
public async Task<IActionResult> DownloadFiles()
{
...
return File(outputMemStream, "application/octet-stream", "Documents.zip");
}

How do I use response from an web api returning an image?

I have two web asp.net mvc based projects.
The first one has an image preview api, is implemented somewhat like this...
private async Task <HttpResponseMessage> GetImage(int id)
{
string filePath = "abstractedforsimplicity.png";
using(var file = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true))
{
byte[] buff = new byte[file.Length];
await file.ReadAsync(buff, 0, (int) file.Length);
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(buff)
};
result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
return result;
}
}
this works, I am able to show a preview with the following url - domain/api/image/3
Now I am a different application where I want to again make use of the same preview. I do not want to expose this api directly, so will be making a proxy api which will be making the call internally.
public HttpResponseMessage GetImage(int id)
{
string tempalteUrl = string.Format("{0}/{1}", ConfigurationManager.AppSettings["rmgpubadmin:template-base-url"], id);
WebClient client = new WebClient();
byte[] bytes = client.DownloadData(tempalteUrl);
// not very sure what should i do here ??
return null;
}
I tried to converting the bytes to an object, but if fails with errors - System.Runtime.Serialization.SerializationException.
The input stream is not a valid binary format. The starting contents (in bytes) are: 89-50-4E-47-0D-0A-1A-0A-00-00-00-0D-49-48-44-52-00 ...
What should i be doing here?

Cannot convert from string to System.IO.Stream

Here's my code for StreamReader in Xamarin Forms What I want is simply read a file and convert it into byte array but when I try this code I simply get this error that is Cannot convert from string to System.IO.Stream
using (var sr = new StreamReader(filename))
{
buffer = new byte[(int)sr.BaseStream.Length];
await sr.ReadAsync(buffer, 0, (int)sr.BaseStream.Length);
}
StreamReader operates upon an existing Stream. But you still need to open or create that underlying stream first by using the device operating system. The process of doing this is slightly different on each platform, and so you can't put that part of your code into the PCL project.
See the section of the documentation titled "Saving and Loading Files" here: https://developer.xamarin.com/guides/xamarin-forms/working-with/files/
One way to do it is by using xamarin dependency service and use FileStream to read the bytes
public byte[] ImageToBinary(string imagePath)
{
FileStream fileStream = new FileStream(imagePath, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[fileStream.Length];
fileStream.Read(buffer, 0, (int)fileStream.Length);
fileStream.Close();
return buffer;
}

c# how to get a stream processed by httpResponse.BinaryWrite

I have the following method that writes a stream in a HttpResponse object.
public HttpResponse ShowPDF(Stream stream)
{
MemoryStream memoryStream = (MemoryStream) stream;
httpResponse.Clear();
httpResponse.Buffer = true;
httpResponse.ContentType = "application/pdf";
httpResponse.BinaryWrite(memoryStream.ToArray());
httpResponse.End();
return httpResponse;
}
In order to test it, I need to recover the processed stream.
Is there someway to read the stream from the httpResponse object?
I have two ideas... one to mock the HttpResponse, and the other is to simulate a web server.
1. Mocking HttpResponse
I wrote this before I knew which mocking framework you used. Here's how you could test your method using TypeMock.
This assumes that you pass your httpResponse variable to the method, changing the method as follows:
public void ShowPDF(Stream stream, HttpResponse httpResponse)
Of course you would change this to passing it to a property on your Page object instead, if it is a member of your Page class.
And here's an example of how you could test using a fake HttpResponse:
internal void TestPDF()
{
FileStream fileStream = new FileStream("C:\\deleteme\\The Mischievous Nerd's Guide to World Domination.pdf", FileMode.Open);
MemoryStream memoryStream = new MemoryStream();
try
{
memoryStream.SetLength(fileStream.Length);
fileStream.Read(memoryStream.GetBuffer(), 0, (int)fileStream.Length);
memoryStream.Flush();
fileStream.Close();
byte[] buffer = null;
var fakeHttpResponse = Isolate.Fake.Instance<HttpResponse>(Members.ReturnRecursiveFakes);
Isolate.WhenCalled(() => fakeHttpResponse.BinaryWrite(null)).DoInstead((context) => { buffer = (byte[])context.Parameters[0]; });
ShowPDF(memoryStream, fakeHttpResponse);
if (buffer == null)
throw new Exception("It didn't write!");
}
finally
{
memoryStream.Close();
}
}
2. Simulate a Web Server
Perhaps you can do this by simulating a web server. It might sound crazy, but it doesn't look like it's that much code. Here are a couple of links about running Web Forms outside of IIS.
Can I run a ASPX and grep the result without making HTTP request?
http://msdn.microsoft.com/en-us/magazine/cc163879.aspx

Resources