I have a ASP.NET MVC Website as Frontend that is connected via WCF (net.tcp streamed response) to a backend running on a different server.
The Backendservice implements a servicecontract that contains the follwoing method
[ServiceContract]
public interface BackendService
{
[OperationContract]
Stream GetDownload(int dataId);
}
The service is hosted with the transfermode as streamed Response.
At the frontend I want to offer the ability to Download the file that is streamed from the Backend.
Because the MessageBodyStream returned from the WCFChannel can't be converted automatically to a Filestream and actionresult I tried to convert it to a Memorystream. So I had to read the full MessageBodyStream and copy it to an Memorystream, that can be returned in an Actionresult as FileStreamResult.
public class MyAspNETMVCController:Controller
{
public FileStreamResult DownloadFile(int DataId)
{
var stream = new MemoryStream();
var netstream = downloadService.GetDownload(rawDataId);
netstream.CopyTo(stream);
stream.Position = 0;
return new FileStreamResult(stream, "application/zip");
}
}
The Files a try to offer are about 4GB and sometimes I get a OutOfMemory Exception. Is there any "nice" way of getting big data from an WCF streaming service and return them as FileStreamResult to the Client?
I do not want a direct connection between the client and the Backend. The complete communication should run over the ASP.NET MVC Website.
Related
I need to stream a file from ASP.NET Core to Blazor WASM using gRPC.
I would like to use the new class DotNetStreamReference added in net6 to allow stream directly to disk using JSInterop (see https://learn.microsoft.com/en-us/aspnet/core/blazor/file-downloads?view=aspnetcore-6.0).
Now, the problem is: gRPC method stream data returning a IAsyncEnumerable<T>, but the DotNetStreamReference class accept only a Stream object as input.
There is a way to convert IAsyncEnumerable<byte[]> to a Stream or eventually return a Stream from a gRPC call?
Thanks
I'm not sure about the gRPC part, but for the 'convert' question, definitely:
var streamContent = new byte[] {};
await foreach(var chunk in your_iasyncenumerable)
{
streamContent.Concat(chunk);
}
Examples exist to read data from an IAsyncEnumerator to the UI in a Blazor app using an internal service.
Examples also exist on how to send an IAsyncEnumerator as an output from a Web API Controller action.
I haven't seen any examples yet how to read an IAsyncEnumerator stream from an API using an HttpClient within a client like Blazor or Xamarin. Everything I've tried so far, only returns the HttpResponseMessage on the client after the async/await foreach loop on the API is done.
HttpResponseMessage response = await _httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
What should the content type be (Produces attribute) on the HttpGet action? What should the Accept value be on the request header from the HttpClient?
[HttpGet]
[Produces("application/json")]
public async IAsyncEnumerable<Data> Get(CancellationToken cancellationToken)
{
var dbSet = _dbContext.TableName.AsNoTracking().AsAsyncEnumerable().WithCancellation(cancellationToken).ConfigureAwait(false);
await foreach (var i in dbSet.ConfigureAwait(false))
{
var item = new Data
{
Id = i.Id,
Name = i.Name
};
yield return item;
}
}
You'd better not do it with raw http 1.1 request-response model, which is not designed for this, and streaming objects are different from downloading files.
With websocket or http2.0 that support multiplexing, you can serialize each elements produced by the IAsyncEnumerable and deserialize them in the client. But still this is manually controlled and not worth.
You could use gRPC which is officially supported by ASP.NET Core and supports object streaming. It also supports many more languages and has strongly typed interface definition in comparison with SignalR which supports JavaScript/.NET/Java only and .
I am trying to export some data to excel and store that excel in AWS S3. Our current architecture is like,
we get data from database and manipulate it as per our needs. This is done is one API call.
We need to pass that data as stream to another API ( specifically designed to interact with AWS S3)
Store that stream as Excel file in AWS S3.
So far what i have achieved is :
I am able to get data from database and convert it to memory stream. I have written another API to receive this stream. But couldn't manage to get to pass memory stream from one API to another API.
1st API :
public async Task<ICollection<UserDTO>> ExportUsers(Guid groupId, HttpRequestMessage request)
{
var ms = // get's memory stream out of data received from database.
var client = new HttpClient
{
BaseAddress = new Uri("http://localhost:58025/")
};
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/bson"));
MediaTypeFormatter bsonFormatter = new BsonMediaTypeFormatter();
//Not sure about BsonMediaTypeFormmater. Juz gave it a try
var response = await client.PostAsync("http://localhost:58025/Resource/Memory", ms, bsonFormatter);
}
2nd API :
[HttpPost]
[Route("Resource/Memory", Name = "UploadMemory")]
public async Task<IHttpActionResult> UploadMemoryFile(MemoryStream memory)
{
// Not reaching until here
}
Any help is highly appreciated!!
First time posting! I've been breaking my head on this particular case. I've got a Web application that needs to upload a file towards a web-api and receive an SVG file (in a string) back.
The web-app uploads the file as follows:
using (var client = new WebClient())
{
var response = client.UploadFile(apiUrl, FileIGotEarlierInMyCode);
ViewBag.MessageTest = response.ToString();
}
Above works, but then we get to the API Part:
How do I access the uploaded file? Pseudocode:
public string Post([FromBody]File f)
{
File uploadedFile = f;
String svgString = ConvertDataToSVG(uploadedFile);
return s;
}
In other words: How do I upload/send an XML-file to my Web-api, use/manipulate it there and send other data back?
Thanks in advance!
Nick
PS: I tried this answer:
Accessing the exact data sent using WebClient.UploadData on the server
But my code did not compile on Request.InputStream.
The reason Request.InputStream didn't work for you is that the Request property can refer to different types of Request objects, depending on what kind of ASP.NET solution you are developing. There is:
HttpRequest, as available in Web Forms,
HttpRequestBase, as available in MVC Controllers
HttpRequestMessage, as available in Web API Controllers.
You are using Web API, so HttpRequestMessage it is. Here is how you read the raw request bytes using this class:
var data = Request.Content.ReadAsByteArrayAsync().Result;
I'm working on an MVC webapplication that streams data from many resources.
My problem is when want to get data (music file) from a stream resource and then stream it to my web page, I don't know how not to download completely and then stream it to my web page.
Here is my webapi code:
[HttpGet]
public HttpResponseMessage Downlaod(int Data)
{
WebClient myWebClient = new WebClient();
Uri u =new Uri("https://api.soundcloud.com/tracks/" + Data + "/stream?client_id=*******************");
byte[] myDataBuffer = myWebClient.DownloadData(u);
MemoryStream st = new MemoryStream(myDataBuffer);
/*heres when i download data and convert it to memory stream*/
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Headers.AcceptRanges.Add("bytes");
result.StatusCode = HttpStatusCode.OK;
result.Content = new StreamContent(st);
result.Content.Headers.ContentLength = st.Length;
result.Content.Headers.ContentType =
new MediaTypeHeaderValue("application/octet-stream");
return result;
}
I want to stream immediately when I receive bytes from my resource.
note: I'm not asking about how to stream data to the client it's about streaming from server to server.
I want to get file from another server and stream it to my clients without downloading the full content before start streaming.
note2: I also don't want to download the full content in once because the full content is very big, I want to get a byte from my content and then send that byte to the client not downloading the full content.
I think I'm doing it in wrong way and it is not possible with an MVC application if anyone can introduce an application that can proxy bytes from destination to client it would be the answer. the main reason that I want this,is to proxy a music file from my content server to a javascript music player and not to expose the main file.