locked
Cancelling a file Upload: "Page cannot be displayed" error RRS feed

  • Question

  • User1668405831 posted

    Hi,

    I want to cancel a file Upload if the file size is found to be too large. But user is getting the "Page cannot be displayed" error when this happens.

    I am reading the header content in Application_BeginRequest of Global.asax and determining the size of the file, before the entire file is uploaded (we do not want to receive the entire file and then say it was too large)...

    The code has to somehow end the request after the length is checked, or the complete file upload will go through after this. The problem is, any code used for this, like Response.end, Response.redirect, etc., causes a "Page cannot be displayed" error to be shown to the user (using IE7). So there is no way for the user to know that the upload was not allowed because of file size.

    I have changed values for httpRuntime maxRequestLength in web.config and machine.config to 2 GB i.e. 2097151 (this value is in KBytes, I believe), and trying to prevent uploads of files over 100 KB.

    I have read many posts on it, and tried all kinds of code (including custom httpmodules), but the "Page cannot be displayed" error is just not going away.

    Can you please help? Any suggestion you can provide is most appreciated.

    Here is the current code:

    Aspx page:

    Tried each kind of file inputs:

            <input name="File1" type="file" />
            <br />
            <asp:FileUpload ID="File2" runat="server" />
            <br />
     

    Global.asax:

        Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
            ' Fires at the beginning of each request
            Dim length As Integer
            'Dim app As HttpApplication = CType(sender, HttpApplication)
            Dim maxUploadBytes As Integer = 100000

            Dim WorkerRequestKey As String = "worker1"
            Dim worker As HttpWorkerRequest
            Dim context As HttpContext
            Dim provider As IServiceProvider

            context = HttpContext.Current
            'worker = context.Items(WorkerRequestKey)
            provider = CType(context, IServiceProvider)
            worker = CType(provider.GetService(GetType(HttpWorkerRequest)), HttpWorkerRequest)

            If worker.HasEntityBody() Then
                length = worker.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength)

                'Response.Write("httpworkerrequest hc length = " & length & "<br>")
                'Response.Write("max upload bytes = " & maxUploadBytes & "<br>")
                'Response.End()

                If length > maxUploadBytes Then
                    Response.Write("limit exceeded")
                    Response.End()
                    Throw New HttpException(404, "Not found")

                    '    Response.Redirect("error.aspx")
                    context.RewritePath("error.aspx")
                End If
            End If

        End Sub

    Monday, May 4, 2009 3:00 PM

Answers

  • User2019766093 posted

    If you try my originally posted code, you can see that the upload can indeed be interrupted before receiving the entire file. You have to use the header mechanism for this ( length = worker.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength) ), I'm not sure if Request.contentlength does the same thing. If you try HeaderContentLength and use a 1 Gig file, you will see that the "Page cannot be displayed" shows up almost immediately. It does this for me.

    You may also have to first change the maxRequestLength value in web.config to 2 GB., and also set the timeout in seconds to a high value. If you then try to upload a 1 GB file, you will see this in action. If you try a 2 GB file, you may have to increase the maxRequestLength value higher than this.

    Request.ContentLength is the same thing. The value is set from the request header.

    I tried setting maxRequestLength to 4 gig and got an error specifying that 2 gig is the max value that can be set. It would have been nice if the documentation had specified that.

    I found that the pause I was experiencing was IE loading up the file I wanted to upload prior to sending it to the server, so I'm probably wrong that IIS is receiving the entire request before handing off to .net. I did find that if the file was small enough, I would get the exception. So maybe it's receiving the request body asynchronously and if the file is small enough, it just happens to finish uploading before BeginApplication is called. In this case, the client would then think the request was successfully sent and wait for a response.

    The thought also crossed my mind about the client not understanding that the server cancelled the request, but then there are several such commands in the .NET api to do exactly this (HttpContext.Current.RewritePath, HttpApplication.CompleteRequest, etc. ). I'm wondering what is the use of these commands if they only result in showing "Page cannot be displayed" to the user. Surely there must be some way to proceed gracefully after these are called...

    Those don't exactly cancel the request. RewritePath changes the internal path to be processed - kind of like Server.Transfer. CompleteRequest bypasses the rest of the processing of the request and jumps to EndRequest which is the last event in the pipelline. Neither one of them actually interrupts the request as it's being sent and both still end in a response being sent back to the client. If I'm right in what I said above about the request being received asynchronously, then perhaps if the request hasn't finished being received by the time the CompleteRequest method is called, the client will show the same message.

     I ran the test from FireFox and got a more helpful message, "The network link was interrupted while negotiating a connection. Please try again." This is misleading as the interruption is happening after the connection was negotiated but before it was finsihed being transmitted.

    Anyways, I still think because the request is being interrupted before completing, you won't be able to send a response back to the cilent because the client won't be listening for one.

    Hopefully someone that actually KNOWS will post instead of our speculation.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, May 6, 2009 10:39 AM

All replies

  • User1677448765 posted

     This is the simple and most basic type of programming..

    web.config

    add the httpRuntime tag like this

     <httpRuntime maxRequestLength="2097151" delayNotificationTimeout="60"/>

    then in .aspx 

    add these

    <asp:FileUpload ID="FileUpload1" runat="server" />
            <asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click"
                style="height: 26px" />

     

    .cs(code behind)

    protected void Button1_Click(object sender, EventArgs e)
        {
            string path = Server.MapPath("~/file/");
            string filename = FileUpload1.FileName;
            string file = Path.Combine(path, filename);
            if (FileUpload1.HasFile)
            {
                if (FileUpload1.PostedFile.ContentLength > 100000)
                {
                    Response.Write("error");
                }
                else
                {
                    FileUpload1.SaveAs(file);
                }
            }
        }

    Tuesday, May 5, 2009 12:14 AM
  • User1668405831 posted

    Anup,

    Thanks for your reply.

    But the problem is that this code does not start to execute until the entire file has been sent to the server from the user's PC.

    We are trying to avoid the situation where a user waits a long time to upload a file and later is shown a message that the file was too large. Some of their connections are slow and they try to upload files of size 1 GB, they may have to wait over an hour for this to happen. It is also a drain on bandwidth, and other server resources.

    Since the file info is in the header, it can be checked in Application_Beginrequest. However, like I described, if I use statements like Response.end etc. after this check, the user sees "Page cannot be displayed".

    Please let me know if you have any other thoughts on the issue.

    Thanks in advance...

    Tuesday, May 5, 2009 11:48 AM
  • User2019766093 posted

    Nice idea, but I don't think you can do this. I believe IIS receives the entire request (hence the entire file upload) before it hands execution off to .net.

    I tested this using the BeginRequest:

     

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        if (Request.ContentLength > 4096)
        {
            throw new Exception("here");
        }
    }
    

     

    When I uploaded a 2meg file, the exception was thrown as expected. I then tried a 2gig file. After a significant pause (network traffic shows the upload in progress), IE7 gave me the "Page cannot be displaed" message. This appears to support my hypothesis that IIS receives the entire request before handing off.

    We just don't get hooked in early enough.

    If think you think about network programming (sockets and streams et al) and how http request/response are done, this actually makes sense. When the client sends a request, it opens a connection to the server and starts transmitting data. Normally, after the successful transmission of the request, the client expects and waits for a response. If instead the server were to close the connection early (interrupting the file upload), the client would think there's an error with sending the request and would not wait for a response. So even if you could interrupt the file upload, you couldn't send anything back - even a redirect.

    Tuesday, May 5, 2009 4:09 PM
  • User1668405831 posted

    Hi jshepler,

    Thanks for your reply.

    If you try my originally posted code, you can see that the upload can indeed be interrupted before receiving the entire file. You have to use the header mechanism for this ( length = worker.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength) ), I'm not sure if Request.contentlength does the same thing. If you try HeaderContentLength and use a 1 Gig file, you will see that the "Page cannot be displayed" shows up almost immediately. It does this for me.

    You may also have to first change the maxRequestLength value in web.config to 2 GB., and also set the timeout in seconds to a high value. If you then try to upload a 1 GB file, you will see this in action. If you try a 2 GB file, you may have to increase the maxRequestLength value higher than this.

    So the upload can be interrupted, it is just the "error display" part that is not happening.

    The thought also crossed my mind about the client not understanding that the server cancelled the request, but then there are several such commands in the .NET api to do exactly this (HttpContext.Current.RewritePath, HttpApplication.CompleteRequest, etc. ). I'm wondering what is the use of these commands if they only result in showing "Page cannot be displayed" to the user. Surely there must be some way to proceed gracefully after these are called...

    Please let me know if you have any other thoughts on this issue.

    Thanks in advance...


     

    Tuesday, May 5, 2009 5:12 PM
  • User1668405831 posted


    Tuesday, May 5, 2009 5:39 PM
  • User-122480877 posted

    Instead of throwing an error why dont you in the controls code behind like this

    check if  NewsImageFileUpload.PostedFile.ContentLength greater than Maxupload

    alert("Sorry the file you have selected is to big, please select another")

    else do upload

    using Response.Write() from experince cause's alot of problems by its self in advanced aplications and is messy

    also you should not try and handle a request like this from global.asax as in most cases the onclick event for a control is managed before Application_BeginRequest and if you put break points on every section of code you will see this in action..

    Tuesday, May 5, 2009 11:19 PM
  • User2019766093 posted

    If you try my originally posted code, you can see that the upload can indeed be interrupted before receiving the entire file. You have to use the header mechanism for this ( length = worker.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength) ), I'm not sure if Request.contentlength does the same thing. If you try HeaderContentLength and use a 1 Gig file, you will see that the "Page cannot be displayed" shows up almost immediately. It does this for me.

    You may also have to first change the maxRequestLength value in web.config to 2 GB., and also set the timeout in seconds to a high value. If you then try to upload a 1 GB file, you will see this in action. If you try a 2 GB file, you may have to increase the maxRequestLength value higher than this.

    Request.ContentLength is the same thing. The value is set from the request header.

    I tried setting maxRequestLength to 4 gig and got an error specifying that 2 gig is the max value that can be set. It would have been nice if the documentation had specified that.

    I found that the pause I was experiencing was IE loading up the file I wanted to upload prior to sending it to the server, so I'm probably wrong that IIS is receiving the entire request before handing off to .net. I did find that if the file was small enough, I would get the exception. So maybe it's receiving the request body asynchronously and if the file is small enough, it just happens to finish uploading before BeginApplication is called. In this case, the client would then think the request was successfully sent and wait for a response.

    The thought also crossed my mind about the client not understanding that the server cancelled the request, but then there are several such commands in the .NET api to do exactly this (HttpContext.Current.RewritePath, HttpApplication.CompleteRequest, etc. ). I'm wondering what is the use of these commands if they only result in showing "Page cannot be displayed" to the user. Surely there must be some way to proceed gracefully after these are called...

    Those don't exactly cancel the request. RewritePath changes the internal path to be processed - kind of like Server.Transfer. CompleteRequest bypasses the rest of the processing of the request and jumps to EndRequest which is the last event in the pipelline. Neither one of them actually interrupts the request as it's being sent and both still end in a response being sent back to the client. If I'm right in what I said above about the request being received asynchronously, then perhaps if the request hasn't finished being received by the time the CompleteRequest method is called, the client will show the same message.

     I ran the test from FireFox and got a more helpful message, "The network link was interrupted while negotiating a connection. Please try again." This is misleading as the interruption is happening after the connection was negotiated but before it was finsihed being transmitted.

    Anyways, I still think because the request is being interrupted before completing, you won't be able to send a response back to the cilent because the client won't be listening for one.

    Hopefully someone that actually KNOWS will post instead of our speculation.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, May 6, 2009 10:39 AM
  • User2019766093 posted

    Instead of throwing an error why dont you in the controls code behind like this

    check if  NewsImageFileUpload.PostedFile.ContentLength greater than Maxupload

    Because PostedFile.ContentLength is after the file has been uploaded. He wants to interrupt the request and prevent the upload from even occuring.

     

    Wednesday, May 6, 2009 10:47 AM