1

I know that I can return a file from a controller action using code like:

public ActionResult SomeAction()
{
    return File(PathToTheFile);
}

There is also an overload that accepts a Stream rather than a file path.

In my case, I dynamically create a CSV file based on a database query. It would be simpler to write that CSV file directly to the response, and have the response treated as a file. Is it possible to do that? How?

EDIT

I assume that I would be writing to some sort of stream, but what kind of stream and who is responsible for disposing it?

Eric J.
  • 147,927
  • 63
  • 340
  • 553
  • So the user never needs to download the CSV file? Why create a CSV file (or any file) at all? Just query the database and display that data to the user on a page (formatted the way you want) – rwisch45 Jan 31 '14 at 03:18
  • @rwisch45: The file should be downloaded, I just do not want to temporarily write it to the file system. – Eric J. Jan 31 '14 at 04:18
  • possible duplicate of [Writing to Output Stream from Action](http://stackoverflow.com/questions/943122/writing-to-output-stream-from-action) – Eric J. Feb 05 '14 at 06:54

1 Answers1

2

Edit:

As you create output dynamically and would like to avoid creating file and memory stream to improve performance and avoid additional I/O, a simple solution is to directly write to Http Response. The following code is a example that works for me. You may use the same method for your data.

public ActionResult getFile()
    {
        Response.AddHeader("Content-Disposition", "attachment; filename=myVFile.csv");
        Response.ContentType = "text/csv";


        //sample data 
        string[] data = { "-4", "-3", "-2", "-1", "0", "1", "2", "3" };


        //Query data with LINQ  - This can be done in diffrent ways 
        (from item in data
         where
            //Some conditions
            item != "-4"
         select
         //Select whatever you want to be in the output 
         item
         )
        .ToList()
        .ForEach(
              //Write items from your LINQ Query to HTTP Response 
               item => Response.Write(item + ",")
        );

        //You can use a foreach loop instead of chaining ForEach in LINQ as above 


        Response.End();

        return Content(null);
    }
Maddy
  • 300
  • 1
  • 8
  • How would CreateMyFile write to a stream? What kind of stream? How is the stream disposed? – Eric J. Jan 31 '14 at 04:19
  • If I was going to stream a file to Response, I would use MemoryString as below : private static Stream CreateMyFile() { string filename = "myfile.csv"; byte[] content = File.ReadAllBytes(filename); MemoryStream ms = new MemoryStream(); ms.Write(content, 0, (int)content.Length); ms.Position = 0; return ms; } You may replace the line `byte[] content = File.ReadAllBytes(filename)` to create content from your database or any other way you wish .... – Maddy Jan 31 '14 at 04:57
  • But that requires a) actually having a file on disk (trying to avoid that), and b) reading all of the bytes into memory before streaming them out. – Eric J. Jan 31 '14 at 05:18
  • how do you create your final content that you would like to stream to response as downloadable file? Is it by an iteration through a collection or a LINQ query? Can you paste your content creation method here so that can help to suggest a better solution. – Maddy Feb 02 '14 at 23:33
  • I iterate a Linq query. I *could* write the results of the link query to a file stream and then return that file as the ActionResult. However, I'm trying to avoid writing that file. – Eric J. Feb 04 '14 at 03:07