locked
Problem in HTTPHandlers RRS feed

  • Question

  • User1601727008 posted

    Hi I am using HTTPHandler. I have created  a page(.ashx) .If I use small file (less then 10 MB) it wokrs fine. But if I provide a file name with more then 100MB then the Respone.WriteFile(".." ) fails to execute ?

    public void ProcessRequest (HttpContext context) {

    context.Response.ContentType = "media";

    context.Response.Write("Files/myvideo.wmv"); // myvideo.wmv is more then 100 MB in size.

    }

     I think Response.WriteFile have some limitation for writing a file

     

    Saturday, May 26, 2007 3:30 AM

Answers

  • User1335583151 posted

    Hello my friend,

    The WriteFile method takes up a lot of server resources as the entire file is held in memory.  Not only does it impose limits, it will leave the website vulnerable to Denial Of Service attacks.  A solution is to send the file in small pieces: -


        protected void Page_Load(object sender, EventArgs e)
        {
            string dlDir = "Downloads/";
            string strFileName = Request.QueryString["FileName"];

            string path = Server.MapPath(dlDir + Request.QueryString["FileName"]);
            System.IO.FileInfo toDownload = new System.IO.FileInfo(path);

            if (toDownload.Exists)
            {
                const int ChunkSize = 10000;
                Byte[] buffer = new Byte[ChunkSize];
                Response.Clear();

                using (System.IO.FileStream iStream = System.IO.File.OpenRead(path))
                {
                    long dataLengthToRead = iStream.Length;
                    Response.ContentType = "application/octet-stream";
                    Response.AddHeader("Content-Disposition", "attachment; filename=" + toDownload.Name);

                    while (dataLengthToRead > 0 && Response.IsClientConnected)
                    {
                        int lengthRead = iStream.Read(buffer, 0, ChunkSize);
                        Response.OutputStream.Write(buffer, 0, lengthRead);
                        Response.Flush();
                        dataLengthToRead = dataLengthToRead - lengthRead;
                    }
                }
                Response.Close();
            }
            else
            {
                Response.Write("File not found");
            }
        }

    Note that there is a 2GB download size limit in IIS.  If you intend to go over this limit, I would suggest using FTP.   

    Kind regards

    Scotty


     

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, May 26, 2007 5:17 AM
  • User1335583151 posted

    Hello again my friend,

    It should work on live fine, but I suggest you have the following functionality on your site. 

    If you go to a site like romnation.net that allows you to download big files, before being allowed to download a file it shows you an image containing 4 numbers and you are asked to put these numbers in a text box and if correct, you are redirected to be allowed to download the file.  The number changes each time.  This is to stop many requests at the same time by a malicious user from crashing your server. 

    If you want an example code page that does this, I suggest you ask for it in a separate forum question so that other experts will see this new question as my knowledge on how to do this is vague, but I would guess it is done by having a .NET page that returns an image, not an aspx/html page via code. 

    Kind regards

    Scotty

     

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, May 28, 2007 8:36 AM

All replies

  • User1335583151 posted

    Hello my friend,

    The WriteFile method takes up a lot of server resources as the entire file is held in memory.  Not only does it impose limits, it will leave the website vulnerable to Denial Of Service attacks.  A solution is to send the file in small pieces: -


        protected void Page_Load(object sender, EventArgs e)
        {
            string dlDir = "Downloads/";
            string strFileName = Request.QueryString["FileName"];

            string path = Server.MapPath(dlDir + Request.QueryString["FileName"]);
            System.IO.FileInfo toDownload = new System.IO.FileInfo(path);

            if (toDownload.Exists)
            {
                const int ChunkSize = 10000;
                Byte[] buffer = new Byte[ChunkSize];
                Response.Clear();

                using (System.IO.FileStream iStream = System.IO.File.OpenRead(path))
                {
                    long dataLengthToRead = iStream.Length;
                    Response.ContentType = "application/octet-stream";
                    Response.AddHeader("Content-Disposition", "attachment; filename=" + toDownload.Name);

                    while (dataLengthToRead > 0 && Response.IsClientConnected)
                    {
                        int lengthRead = iStream.Read(buffer, 0, ChunkSize);
                        Response.OutputStream.Write(buffer, 0, lengthRead);
                        Response.Flush();
                        dataLengthToRead = dataLengthToRead - lengthRead;
                    }
                }
                Response.Close();
            }
            else
            {
                Response.Write("File not found");
            }
        }

    Note that there is a 2GB download size limit in IIS.  If you intend to go over this limit, I would suggest using FTP.   

    Kind regards

    Scotty


     

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, May 26, 2007 5:17 AM
  • User1601727008 posted
    Thanks allot for your support. I really need that one [:D]. But I am confused in using this code. If you could help me out here also... please....<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p>What I am doing is: On  Media.aspx.cs I have written <o:p></o:p>

    public string url = "";

    protected void Page_Load(object sender, EventArgs e)

    {

    url = MediaHandler.ashx?filename=test.wmv"; // Passing file name to HTTPHandler page.

    }

    Now I had chaned my code to url = MediaHandler.aspx?filename=test.wmv

    But its not working ...actually it play the file but stop in between . Please help

    Thanks and Regards

    Shikhar

    Monday, May 28, 2007 1:58 AM
  • User1335583151 posted

    Hello again,

    I am just wondering what the rest of your code is and why you are using a HTTP handler for this. 

     

    Kind regards

    Scotty

     

    Monday, May 28, 2007 5:23 AM
  • User1601727008 posted

    Thanks again I have changed my code to :

    System.IO.Stream iStream = null;

    // Buffer to read 1000K bytes in chunk:

    byte[] buffer = new Byte[1000000];

    // Length of the file:

    int length;

    // Total bytes to read:

    long dataToRead;

    // Identify the file to download including its path.

    string filepath = "c:\\spiderman.wmv";

    // Identify the file name.

    string filename = System.IO.Path.GetFileName(filepath);

    try

    {

    // Open the file.

    iStream = new System.IO.FileStream(filepath, System.IO.FileMode.Open,System.IO.FileAccess.Read, System.IO.FileShare.Read);

     

    // Total bytes to read:

    dataToRead = iStream.Length;

    Response.ContentType =
    "application/octet-stream";

    Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);

    // Read the bytes.

    while (dataToRead > 0)

    {

    // Verify that the client is connected.

    if (Response.IsClientConnected)

    {

    // Read the data in buffer.

    length = iStream.Read(buffer, 0, 1000000);

    // Write the data to the current output stream.

    Response.OutputStream.Write(buffer, 0, length);

    // Flush the data to the HTML output.

    Response.Flush();

    buffer =
    new Byte[1000000];

    dataToRead = dataToRead - length;

    }

    else

    {

    //prevent infinite loop if user disconnects

    dataToRead = -1;

    }

    }

    }

    catch (Exception ex)

    {

    // Trap the error, if any.

    Response.Write("Error : " + ex.Message);

    }

    finally

    {

    if (iStream != null)

    {

    //Close the file.

    iStream.Close();

    }

    }

     

    Altho it is working fine on my local machine but I am afraid that it work in live or not

    Monday, May 28, 2007 6:55 AM
  • User1335583151 posted

    Hello again my friend,

    It should work on live fine, but I suggest you have the following functionality on your site. 

    If you go to a site like romnation.net that allows you to download big files, before being allowed to download a file it shows you an image containing 4 numbers and you are asked to put these numbers in a text box and if correct, you are redirected to be allowed to download the file.  The number changes each time.  This is to stop many requests at the same time by a malicious user from crashing your server. 

    If you want an example code page that does this, I suggest you ask for it in a separate forum question so that other experts will see this new question as my knowledge on how to do this is vague, but I would guess it is done by having a .NET page that returns an image, not an aspx/html page via code. 

    Kind regards

    Scotty

     

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, May 28, 2007 8:36 AM