Blazor Server create link to download file from byte array - blazor-server-side

I have a method in my code behind to retrieve a get a pdf file from an API and return the byte[]
byte[] byteArray = response.Content.ReadAsByteArrayAsync().Result; ;
using (MemoryStream pdfStream = new MemoryStream())
{
pdfStream.Write(byteArray, 0, byteArray.Length);
pdfStream.Position = 0;
return new FileStreamResult(pdfStream, "application/pdf");
}
How in Blazor server to I create a link in my .razor component to consume this byte[] so that when the user clicks the link, it triggers the file download?

Your solution is close because you're creating the appropriate result, but you simply need the method that returns it.
Set up your API controller like the following:
[ApiController]
public class DownloadController : ControllerBase {
[HttpGet]
public ActionResult Get() {
byte[] byteArray = response.Content.ReadAsByteArrayAsync().Result; ;
using (MemoryStream pdfStream = new())
{
pdfStream.Write(byteArray, 0, byteArray.Length);
pdfStream.Position = 0;
var result = FileStreamResult(pdfStream, "application/pdf");
result.FileDownloadName = "sample.txt";
return result;
}
}
}

Related

CopyToAsync() dont' fill the memory stream

i'm using xamarin.forms app and need to save file(it this situation pdf file). This is my scenario: I'm using media plugin to save images with camera and from that images with PdfDocument object i generate PDF file:
PdfDocument document = new PdfDocument();
for (int i = 0; i < Images.Count(); i++)
{
PdfPage page = document.Pages.Add();
PdfGraphics graphics = page.Graphics;
Stream imageStream = Images.ElementAt(i);
PdfBitmap image = new PdfBitmap(imageStream);
page.Graphics.DrawImage(image, new PointF(40, 100));
}
MemoryStream stream = new MemoryStream();
document.Save(stream);
document.Close(true);
String localPath =
Task.Run(() => DependencyService.Get<ISave>().SaveFile(stream, "test.pdf")).Result;
And everything is working fine, its generates me pdf document with pages stream is filled with bytes, and the problem is in this SaveFile:
[assembly: Dependency(typeof(Save))]
namespace PdfSave.Droid.Shared
{
public class Save: ISave
{
private readonly string _rootDir = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "TestFolder");
public async Task<string> SaveFile(Stream pdfStream, string fileName)
{
if (!Directory.Exists(_rootDir))
Directory.CreateDirectory(_rootDir);
var filePath = Path.Combine(_rootDir, fileName);
using (var memoryStream = new MemoryStream())
{
await pdfStream.CopyToAsync(memoryStream);
File.WriteAllBytes(filePath, memoryStream.ToArray());
}
return filePath;
}
}
the problem is in this line
await pdfStream.CopyToAsync(memoryStream);
the memory stream is empty! . Anyone know what should might be the problem?

SerializeObject and DeserializeObject

I use this following code but it gives error
Service1.svc.cs
public static byte[] SerializeObject<T>(T obj)
{
using (MemoryStream ms = new MemoryStream())
{
using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateBinaryWriter(ms))
{
DataContractSerializer dcs = new DataContractSerializer(typeof(T));
dcs.WriteObject(writer, obj); writer.Flush();
return ms.ToArray();
}
}
}
client code Windows phone
public static T DeserializeObject<T>(byte[] xml)
{
using (MemoryStream memoryStream = new MemoryStream(xml))
{
using (XmlDictionaryReader reader = XmlDictionaryReader.CreateBinaryReader(memoryStream, XmlDictionaryReaderQuotas.Max))
{
DataContractSerializer dcs = new DataContractSerializer(typeof(T));
return (T)dcs.ReadObject(reader);
}
}
}
I call this DeserializeObject from below code
void svc_Get_Conn(object send, GetConnCompletedEventArgs e)
{
CookieContainer con =DeserializeObject<CookieContainer>(e.Result);
}
This gives following error
Message = "Type 'System.Net.PathList' with data contract name 'PathList:http://schemas.datacontract.org/2004/07/System.Net' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using...
How to solve this?
CookieContainer can't be serializable. Check this workaround
cheers

Using wcf how to upload a image

using wcf/wcf web services to upload a images give me with example?
In my project i want to upload image by using WCF
Basically you should use WCF streaming.
[ServiceContract]
public interface ITransferService
{
[OperationContract]
void UploadFile(RemoteFileInfo request);
}
public void UploadFile(RemoteFileInfo request)
{
FileStream targetStream = null;
Stream sourceStream = request.FileByteStream;
string uploadFolder = #"C:\\upload\\";
string filePath = Path.Combine(uploadFolder, request.FileName);
using (targetStream = new FileStream(filePath, FileMode.Create,
FileAccess.Write, FileShare.None))
{
//read from the input stream in 65000 byte chunks
const int bufferLen = 65000;
byte[] buffer = new byte[bufferLen];
int count = 0;
while ((count = sourceStream.Read(buffer, 0, bufferLen)) > 0)
{
// save to output stream
targetStream.Write(buffer, 0, count);
}
targetStream.Close();
sourceStream.Close();
}
}
The easiest way is to convert the image to a byte array before sending it, and then converting it back to an image on the destination site.
Here are two methods for doing just that:
public byte[] ImageToByteArray( Image image)
{
var ms = new MemoryStream();
image.Save(ms, ImageFormat.Png);
return ms.ToArray();
}
public static Image ByteArrayToImage(byte[] byteArray)
{
var ms = new MemoryStream(byteArray);
return Image.FromStream(ms);
}
That means your web service can have a method something like this:
public void UploadImage( byte[] imageData )
{
var image = ByteArrayToImage( imageData );
//save image to disk here, or do whatever you like with it
}

How to read .mp3 files in wcf?

How to read the .mp3 audio files ?
I wrote the following code.
public static byte[] ReadFully(Stream stream)
{
byte[] buffer = new byte[32768];
using (MemoryStream ms = new MemoryStream())
{
while (true)
{
int read = stream.Read(buffer, 0, buffer.Length);
if (read <= 0)
return ms.ToArray();
ms.Write(buffer, 0, read);
}
}
It accepts .3gp,.caf foramat streams .why it's not taking .mp3 files?
}
I used the below code to download a mp3 file from my REST WCF Service:
[WebGet]
public Stream GetMp3()
{
byte[] buffer;
WebOperationContext.Current.OutgoingResponse.ContentType = "audio/mp3";
using (FileStream ms = new FileStream(#"C:\Sample.mp3", FileMode.Open))
{
int length = (int)ms.Length;
WebOperationContext.Current.OutgoingResponse.ContentLength = length;
buffer = new byte[length];
int sum = 0;
int count;
while ((count = ms.Read(buffer, sum, length - sum)) > 0)
{
sum += count;
}
ms.Close();
}
return new MemoryStream(buffer);
}
UPDATE: Upload an mp3 file to Restful WCF service
Server side method:
[WebInvoke]
public string RecieveMp3(Stream mp3Stream)
{
byte[] buffer = new byte[5000000];
using (FileStream ms = new FileStream("C:\\Temp\\Test1.mp3", FileMode.OpenOrCreate))
{
int read = mp3Stream.Read(buffer, 0, buffer.Length);
ms.Write(buffer, 0, read);
}
return "Recieved Mp3 file";
}
NOTE:
1. Make sure that you have permissions on the folder to write the mp3 file for the user associated with the app pool under which the wcf service is running
2. For testing purpose i have hard coded the byte array size to be a large value.
Client to call the service:
private string UseRestSharpApproachForFiles(string serviceBaseUrl, string resourceUrl, Method method, string filepath)
{
var client = new RestClient();
client.BaseUrl = serviceBaseUrl;
var request = new RestRequest(method) { DateFormat = DataFormat.Xml.ToString(), Resource = resourceUrl };
request.AddFile("stream", filepath);
var response = client.Execute(request);
string responseString;
if (response.StatusCode == HttpStatusCode.OK)
{
responseString = HttpUtility.HtmlDecode(response.Content);
}
else
{
responseString = response.StatusDescription + " --------------------" + HttpUtility.HtmlDecode(response.Content);
}
return responseString;
}
Am using the 3rd party dll for invoking the rest service called RestSharp.

Protobuf-net Extension interfaces

I have a problem understanding protobuf-net extensions and how they exactly work. I need to serialize a 2D custom class array and so I decited to wrap it into a class something like:
class CustomData : IExtension
{
private CustomClass[,] data;
public CustomClass this[int index_X, int index_Y]
{
get
{
return data[index_X, index_Y];
}
set
{
data[index_X, index_Y] = value;
}
}
public Stream BeginQuery()
{
var stream = new MemoryStream();
int pos = 0;
byte[] packedData = SomeStaticClass.ConvertToByteArray(data)
using(var writer = new ProtoWriter(stream, null, null))
{
ProtoWriter.WriteFieldHeader(1, WireType.String, writer);
ProtoWriter.WriteBytes(packedData, writer);
}
return stream;
}
public void EndQuery(Stream stream)
{
stream.Close();
}
//... and the other 3 implemented funcs from IExtension
}
So this ofcourse is in a custom IExtensible which has GetExtensionObject() returning an instance of the CustomData object. The problem comes when I try to append extension data to an instance. Here is what I'm doing:
public void DoAppend()
{
var stream = new MemoryStream();
using (ProtoWriter writer = new ProtoWriter(stream, null, null))
{
var test = new CustomExtensibleClass(300, 300);
ProtoWriter.AppendExtensionData(test, writer);
}
var result = stream.ToArray();
}
The problem is that "result" contains no data. I expected that the data I appended and written via BeginQuery() will be transfered to the stream of the ProtoWriter but I suppose this is not the case.
Can somebody explaing what I am doing wrong or at least how can use the appended data?