1

I'm using ASP.NET 4, EF 4 and FILESTREAM in SQL 2008 to add/read files to the DB. I'm able to upload files just fine, but I'm not able to retrieve the files the way I want to. Here's what I'm doing -

  1. I have a grid which displays a list of files. Each line item is a file with a CommandName and CommandArgument set.
  2. The user clicks on any one of these files and I capture the event in the RowCommand event. At this point, I get the ID of the file and retrieve the byte[] from the DB. How do I display a standard download box for the user to Save or Cancel the download?

I can write the stream to a temp file (using System.IO.File.WriteAllBytes) and then do a Server.Transfer to the temp file but I think it's an unnecessary step. Is there a way, I can read the bytes directly to memory, then set the ContentType/MimeType and allow the user to save the file?

I understand that accessing the FILESTREAM file using T-SQL is slower than accessing the same using WIN32 API's (using a combination of the new SystemFile.PathName() & Impersonation) but EF4 makes working with SQL faster so I'm going that route.

Here's the code -

var file = db.Storage.Single(f => f.ID.Equals(fileID)); // fileID is set in CommandArgument
// file.Contents has the byte [].
// display a  standard file download box.

Thanks for any help!

1 Answer 1

1

You probably want to create an .ashx hanlder (assuming you are using asp) and to a Server.Transfer() or Server.Redirect() to that URL.

Alternatively, you could change the GridView to display a hyperlink to the handler URL as well.

Right click in Solution Explorer > New Item > ASP.Net Hanlder.

Code for handler:

public class DownloadFile : IHttpHandler { // add IRequiresSessionState if needed 
  public bool IsReusable { get { return true; } }

  public void ProcessRequest(HttpContext context) {
    var fileID = context.Request.QueryString["fileID"]; // assuming fileID is a string
    var file = db.Storage.Single(f => f.ID.Equals(fileID)); 
    // set the content type
    context.Response.OutputStream.Write(file.Contents, 0, file.Contents.Length);
  }
}

You probably want to add some error checking as well.

Your URL would be something like this: /DownloadFile.ashx?fileID=somefileid

Sign up to request clarification or add additional context in comments.

7 Comments

Yes, I'm using ASP.NET (updated the question with this info). What URL are you talking about? All I have is bytes. Do you want me to write the bytes to a file and do a redirect to that file? If so, I'm trying to avoid that route as I think it may be necessary.
No need to write it to a file, you can write it directly to the OutputStream. I added code to better illustrate the point.
I think I see what you're saying. The link will look something like /GetFile.ashx?id={ID}, and the handler will read the bytes from the DB and write the bytes to the response stream directly without saving to disk?
Thanks for the code sample, I'll give it a shot and report back.
Exactly. Should also make your grid a little simpler.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.