5

In ASP.Net (with C#) I'm trying to create a .DAT file with plain text in it and send it to the browser and force download. I've tried several things but I can't get it working. In my aspx-file there is an ImageButton

<asp:ImageButton ID="btnSave" runat="server" CausesValidation="False" ImageUrl="~/Images/Stages/Database/Save.png" OnClick="btnSave_OnClick" Width="26px" />

In the OnClick-method I'm trying to create the file and send it to the browser.

protected void btnSave_OnClick(object sender, EventArgs e)
{
    string file = "test.dat";
    string fileName = "~\\Stages\\Broekx\\Databanken\\" + file;

    FileStream fs = new FileStream(MapPath(fileName), FileMode.Open);
    long cntBytes = new FileInfo(MapPath(fileName)).Length;
    byte[] byteArray = new byte[Convert.ToInt32(cntBytes)];
    fs.Read(byteArray, 0, Convert.ToInt32(cntBytes));
    fs.Close();

    ImageButton btnSave = (ImageButton)FormViewStagesDummy.FindControl("btnSave");
    btnSave.Visible = false;

    File.Delete(Server.MapPath(fileName));

    if (byteArray != null)
    {
        this.Response.Clear();
        this.Response.ContentType = "text/plain";
        this.Response.AddHeader("content-disposition", "attachment;filename=" + file);
        this.Response.BinaryWrite(byteArray);
        this.Response.End();
        this.Response.Flush();
        this.Response.Close();
    }
}

The file test.dat exists in the correct folder and has to be deleted after it has been read into bytes. I've tried this without deleting the file and that wont work either.

After clicking btnSave the button has to be hidden, so that's why I set the parameter Visible to false.

I've also tried it with content-type "application/octet-stream" or with a PDF file and content-type "application/pdf" but nothing works. The page loads normally and no file is being downloaded.

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
Yoni
  • 325
  • 2
  • 7
  • 15
  • I suspect some part of the response gets send before the headers. I also don't understand how you expect a single response to download a file, and make a button invisible at the same time. – CodesInChaos Feb 14 '12 at 13:47
  • I thought something similar but how can I make this work? – Yoni Feb 14 '12 at 13:49
  • 1
    As a side-note: look at `File.ReadAllBytes` which can replace the 5 lines you use to read the file. You should only do that with very small files though, perhaps up to 10kB. – CodesInChaos Feb 14 '12 at 13:50
  • I don't use webforms, so I can't help you with that. I'd hide the button using javascript, and only then trigger the download. – CodesInChaos Feb 14 '12 at 13:53
  • Tried without hiding the button but doesn't work either. The file is also over 50kb. – Yoni Feb 14 '12 at 13:58
  • The "Read" isn't guaranteed to fill the whole buffer. It returns the real number of bytes read - check that. Use ReadAllBytes instead. – Hans Kesting Feb 14 '12 at 14:12

2 Answers2

3

Is the file string's path actually correct?

this.Response.AddHeader("content-disposition", "attachment;filename=" + file);

Should it not be filename?

Why are you deleting the file before it is written to the response? Would it not make more sense to serve the file via the response and then delete it?

i.e. call

File.Delete(Server.MapPath(fileName));

after the repsonse.

You should try:

Response.TransmitFile( Server.MapPath(fileName) );
Response.End();

TransmitFile is very efficient because it basically offloads the file streaming to IIS including potentially causing the file to get cached in the Kernal cache (based on IIS's caching rules). Response.End();

Seany84
  • 5,526
  • 5
  • 42
  • 67
  • I've tried without deleting the file but it doesn't work either. In the method AddHeader only the suggested name of the file has to be filled. So not the complete path, but only a suggestion for the filename. – Yoni Feb 14 '12 at 13:40
  • Have you tried Response.TransmitFile() ? Instead of BinaryWrite() ? – Seany84 Feb 14 '12 at 13:44
  • A new page did the trick. I create the file, then redirect to a "download" page that only downloads the file and now it works. Your answer is marked as accepted because it was the most helpful to me. – Yoni Feb 15 '12 at 09:26
0
                Response.Clear();
                Response.ClearContent();
                Response.ClearHeaders();
                Response.ContentType = "text/plain";
                Response.AppendHeader("Content-Disposition", "attachment; filename = " + fileName);
                Response.TransmitFile(Server.MapPath("~/foldername/" + fileName));
                Response.End();
Anyname Donotcare
  • 11,113
  • 66
  • 219
  • 392