2

I'm getting a file from a database in byte [] format and want user to see download dialog before Linq will take it from the database. It's in C# and ASP.NET.

Now, it's like this:

  1. User choose a file, click on it.
  2. In code I get id of file clicked and using Linq I'm downloading.
  3. Then I send the file by Response.OutputStream.Write(content, 0, content.Length);
  4. Before a file is downloaded from the database user won't see any download dialog.

What can I do if I want users to see the download dialog before file is downloaded?

Code:
Getting file by id:

public static byte[] getFile(Guid id)
{
    var linqFile =  from file in MyDB.Files
                    where file.IdPliku.Equals(id)
                    select new
                    {
                        Content = file.Content
                    };

     return linqFile.ToList().FirstOrDefault().Content.ToArray();
}

Saving file:

public void SaveFile(Guid fileID, string filename, string mimeTypes)
{
    try
    {
        byte[] content = FileService.getFile(fileID);
        Response.ClearContent();
        Response.ClearHeaders();
        Response.ContentType = mimeTypes;
        Response.AppendHeader("Accept-Ranges", "bytes");
        Response.AppendHeader("Content-Range", string.Format("0-{0}/{1}", content.Length, content.Length));
        Response.AppendHeader("Content-Length", content.Length.ToString());
        Response.AppendHeader("Content-Encoding", "utf-8");
        Response.AppendHeader("Content-Type", Response.ContentType);
        Response.AppendHeader("Content-Disposition", "attachment; filename= " + HttpUtility.UrlEncode(filename));
        Response.OutputStream.Write(content, 0, content.Length);
        //Response.BinaryWrite(content);
        Response.Flush();
    }
    finally
    {
        Response.Close();
    }
}

You are my hope.

Mattaniel
  • 83
  • 1
  • 7
  • And what is supposed to be saved when the user clicks `Save` (since the file is not downloaded)? – Mrchief Aug 12 '11 at 20:29
  • You'd have to output the headers and start the body BEFORE you start building the download. This means no content-length header because the content's not been built yet at that point. – Marc B Aug 12 '11 at 20:31
  • You want the user to accept the download twice, first when he selects the file(via "mock-file") and second when the real file was loaded from database? I cannot imagine that theres a way to avoid the second dialog because otherwise you could pin him something that he hasn't requested, that sounds like a security vulnerability. – Tim Schmelter Aug 12 '11 at 20:46
  • @Tim, file is selected in ListView - user at this moment doesn't see download dialog, it shows up after file is downloaded from DB. User will see only one download dialog per chosen file. – Mattaniel Aug 13 '11 at 11:26
  • @Mrchief and this is what I want - to begin download and show the download dialog before file is ready to be sent. – Mattaniel Aug 13 '11 at 11:26
  • @Marc B maybe if I use some Stream then content-lenght will be known, or maybe it won't be necessary. – Mattaniel Aug 13 '11 at 11:26

1 Answers1

1

your issue is here:

byte[] content = FileService.getFile(fileID);

because in this line you allocate the whole file in the web server's RAM and put everything in there, all content of the file from the database; what happens later does not matter anymore because you have already downloaded from db to web server in this line!!!

I am having such Deja-vu because I am sure I have given exactly the same comment on a very same question few weeks ago. Can't find it now, search for something like this here in SO.

In fact the solution is to stream directly to the output stream of the Response avoiding your byte[] array allocation above, to get this your data layer should of course support it and if it does not you could add a method for this. You want to use SQL Server filestream or something similar.

Davide Piras
  • 43,984
  • 10
  • 98
  • 147
  • 1
    found it, look at this one please: http://stackoverflow.com/questions/6959196/how-to-perform-a-download-instantly-with-asp-net-c – Davide Piras Aug 12 '11 at 21:30
  • I'll try do something with Streams here. Thanks ;). I hope that I can, in some way, stream file from DB by Linq. – Mattaniel Aug 13 '11 at 11:29