Comments (23)
Might not be able to, just a brain dump for now 😄
from carter.
This works perfectly for streams which can be processed in memory, but unfortunately in my case, this doesn't fix the issue. I'm using a producer/consumer pattern to minimise the memory requirements of my service - the data coming from the database could be many hundreds of MB and I'd rather stream it directly to the client.
This means, I'm not likely to have the entire contents of the stream in memory at once and is the cause of the block - StreamCopyOperation.CopyToAsync
won't start copying until the source stream has completed.
The solution (with and without hacky delay) doesn't work for streams larger than my producer/consumer buffer size. :(
from carter.
There's a SendFileAsync
extension on HttpResponse that looks like it may be what you want: https://github.com/aspnet/HttpAbstractions/blob/dev/src/Microsoft.AspNetCore.Http.Extensions/SendFileResponseExtensions.cs#L25
I haven't got time at the moment to check 100%, will try to in a few hours
from carter.
I had a look at that, but I need an IFileInfo
object to use that. I'm streaming data straight from a database so it isn't hitting the filesystem.
from carter.
Ah ok.
In which case, you might be able to do something similar to the internal operation here: https://github.com/aspnet/HttpAbstractions/blob/dev/src/Microsoft.AspNetCore.Http.Extensions/SendFileResponseExtensions.cs#L164
e.g.:
await StreamCopyOperation.CopyToAsync(fs, res.Body, null, CancellationToken.None);
If this does the job, then I think Botwin should probably have a nicer wrapper around it.
from carter.
from carter.
That is very similar to what I had before in Nancy - I didn't realise I could return a Response
in a handler.
from carter.
@JoeStead Your suggestion is promising. My module now ends with:
var cd = new ContentDisposition { FileName = "journal-{type}.csv" };
res.Headers.Add("Content-Disposition", cd.ToString());
res.ContentType = "application/csv";
await StreamCopyOperation.CopyToAsync(CreateExportStream(models, requestLog, ct), res.Body, null, res.HttpContext.RequestAborted);
Still needs work as it looks like something is blocking the stream from completing.
from carter.
Looks like the response blocks because my stream has not yet been written to before passing to CopyToAsync
. Hacking in a forced delay of 1 second fixes the issue, this gives time for at least the CSV headers to have been written. Not ideal. but this has got me moving forward! Thanks for the help.
from carter.
Just having a quick look in the depths of MVC and the FileResultExecutorBase
calls:
Stream outputStream = context.Response.Body;
Stream stream = fileStream;
await StreamCopyOperation.CopyToAsync(fileStream, outputStream, new long?(), 65536, context.RequestAborted);
stream.Dispose();
stream = null;
Do you want to see if you can do what you had before the hacky timeout and see if it works
from carter.
OK this works:
this.Get("/actors/download", async (request, response, routeData) =>
{
using (var mystream = new MemoryStream(Encoding.ASCII.GetBytes("hi")))
{
var cd = new ContentDisposition { FileName = "journal.csv" };
response.Headers.Add("Content-Disposition", cd.ToString());
response.ContentType = "application/csv";
await StreamCopyOperation.CopyToAsync(mystream, response.Body, new long?(), 65536, request.HttpContext.RequestAborted);
}
});
from carter.
@bazwilliams you will have to create your stream first then call CopyToAsync as it will copy what's in your stream into the response body so it makes sense that it hangs if there's nothing inside it.
However that code above is ugly as hell so I think Botwin needs an extension on Response to write a memorystream to the response like the MVC FileStreamResult. Something like FromStream(Stream myStream, string contentType, ContentDisposition contentDisposition = null)
and used like:
this.Get("/actors/download", async (request, response, routeData) =>
{
using (var mystream = new MemoryStream(Encoding.ASCII.GetBytes("hi")))
{
var cd = new ContentDisposition { FileName = "journal.csv" };
await response.FromStream(mystream, "application/csv", cd);
}
});
from carter.
Fancy sending a PR 🤔 👍
from carter.
The Nancy version of this code looks like:
var models = this.journalReader.Read(start, end, type, ct);
return Task.FromResult(new StreamResponse(() => CreateExportStream(models, requestLog, ct), "application/csv")
.AsAttachment($"journal-{type}.csv")
.WithStatusCode(200));
I'll see if I can solve this using pure asp.net first and report back :)
from carter.
Hmm - the StreamResponse()
in Nancy just uses CopyTo()
https://github.com/NancyFx/Nancy/blob/master/src/Nancy/Responses/StreamResponse.cs#L32
There must be something else I need to do here.
from carter.
from carter.
I'll check it out thanks. If I get it working I'll submit a PR!
from carter.
I reckon @danbarua might have some suggestions
from carter.
I'm using a producer/consumer pattern to minimise the memory requirements of my service - the data coming from the database could be many hundreds of MB and I'd rather stream it directly to the client.
Are there any constraints preventing you from writing out the data to file and then returning that file via the web api? That's how most reporting/CSV exports I've seen work.
from carter.
Technically no, but it is a service I'd like to run via lambda or something like that and just not have to worry about having an S3 bucket or local file system constraints.
It is currently deployed to AWS ECS, so I could gain access to the local file system for the duration of the request, but then I have to manage the available space and remove older files. If I were going to do this, I'd consider rewriting the whole thing and that's not something I want to do at the moment.
It's in the same solution as 5 other Ex Nancy, now Botwin projects (all working perfectly), I thought I'd try my luck at this more tricky one :)
from carter.
from carter.
DynamoDb
from carter.
This is definitely not a Botwin issue; I've rewritten the module as an MVC controller and I see the same problem.
Thanks for all the help so far! Looks like this is the right approach, especially after reading an article about streaming video (linked below) and the asp.net code on Github so look forward to the extension suggested above being merged.
However, I think the ProducerConsumerStream I'm using is introducing some kind of deadlock with asp.net. The way I'm using Nancy to do this seems to work, so will revert my work and park for now. I'll be considering a rewrite instead.
http://anthonygiretti.com/2018/01/16/streaming-video-asynchronously-in-asp-net-core-2-with-web-api/
Cheers!
from carter.
Related Issues (20)
- Suggestion: Add functionality to create a "full" solution
- Possible startup performance issue HOT 6
- How to Authorize Endpoint for specific Role HOT 1
- `WithGroupName` and `WithDescription` results in that module not being surface in SwaggerUI HOT 6
- [Question] Is it possible to do property injection on a CarterModulse version 7 and autofac HOT 1
- Conditionaly Load UnLoad Module HOT 1
- How to configure my filters HOT 1
- [QUESTION] Any sample code using .WithOpenApi HOT 1
- Add support for registering an endpoint filter using an endpoint filter factory HOT 1
- [Question] The future of Carter HOT 1
- Endpoints Not Visible in EndpointsApiExplorer HOT 4
- suggest for nested work HOT 1
- Error On Register IN DI HOT 5
- Removed support to apply endpoint conventions globally HOT 2
- Can't find testhost.deps.json HOT 1
- Unable to change the field of the response data body to uppercase HOT 1
- Minimal AP Versioning HOT 2
- Open Api Summary is not drawing on Swagger UI HOT 3
- Trying to get swagger working with my project. HOT 3
- carter is missing NuGet package README file HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from carter.