การรับ "เกินความยาวสูงสุดของคำขอ"


112

ฉันกำลังเขียนฟังก์ชันการอัปโหลดและมีปัญหาในการตรวจจับ "System.Web.HttpException: เกินความยาวสูงสุดของคำขอ" ด้วยไฟล์ที่มีขนาดใหญ่กว่าขนาดสูงสุดที่ระบุhttpRuntimeใน web.config (กำหนดขนาดสูงสุดเป็น 5120) ฉันใช้ง่าย<input>สำหรับไฟล์

ปัญหาคือเกิดข้อยกเว้นก่อนเหตุการณ์คลิกของปุ่มอัปโหลดและข้อยกเว้นเกิดขึ้นก่อนที่โค้ดของฉันจะทำงาน แล้วฉันจะจับและจัดการกับข้อยกเว้นได้อย่างไร?

แก้ไข:ข้อยกเว้นจะเกิดขึ้นทันทีดังนั้นฉันค่อนข้างมั่นใจว่าไม่ใช่ปัญหาการหมดเวลาเนื่องจากการเชื่อมต่อช้า


5
มีใครลองใช้ MVC บ้าง? ดูเหมือนว่าฉันจะจับข้อยกเว้นได้ถูกทาง แต่ก็หยุดไม่ได้ทุกครั้งที่พยายามแสดงหน้าข้อผิดพลาดจะมีข้อยกเว้นเดียวกันเกิดขึ้น
Andy

ข้อความแสดงข้อผิดพลาดนี้ถูกส่งโดย IIS ก่อนที่จะไปถึงคอนโทรลเลอร์ หากต้องการแจ้งให้ผู้ใช้ทราบว่าไฟล์เกินขีด จำกัด การอัปโหลดสูงสุด (ตั้งค่าในการกำหนดค่าเว็บของคุณ) คุณสามารถตรวจสอบขนาดไฟล์ได้โดยตรงผ่าน JS ด้วยเหตุการณ์ onchange ตัวอย่างเช่น<input type="file" id="upload" name="upload" onchange="showFileSize();" />Inside showFileSize()คุณสามารถแสดงข้อความแสดงข้อผิดพลาดตามขนาดไฟล์ของคุณvar input = document.getElementById("upload"); var file = input.files[0];และต่อท้ายแท็ก html
Alfred Wallace

คำตอบ:


97

ไม่มีวิธีง่ายๆในการจับข้อยกเว้นดังกล่าวอย่างน่าเสียดาย สิ่งที่ฉันทำคือแทนที่เมธอด OnError ที่ระดับเพจหรือ Application_Error ใน global.asax จากนั้นตรวจสอบว่าเป็นความล้มเหลวของคำขอสูงสุดหรือไม่และหากเป็นเช่นนั้นให้โอนไปยังหน้าข้อผิดพลาด

protected override void OnError(EventArgs e) .....


private void Application_Error(object sender, EventArgs e)
{
    if (GlobalHelper.IsMaxRequestExceededException(this.Server.GetLastError()))
    {
        this.Server.ClearError();
        this.Server.Transfer("~/error/UploadTooLarge.aspx");
    }
}

เป็นการแฮ็ก แต่โค้ดด้านล่างใช้ได้กับฉัน

const int TimedOutExceptionCode = -2147467259;
public static bool IsMaxRequestExceededException(Exception e)
{
    // unhandled errors = caught at global.ascx level
    // http exception = caught at page level

    Exception main;
    var unhandled = e as HttpUnhandledException;

    if (unhandled != null && unhandled.ErrorCode == TimedOutExceptionCode)
    {
        main = unhandled.InnerException;
    }
    else
    {
        main = e;
    }


    var http = main as HttpException;

    if (http != null && http.ErrorCode == TimedOutExceptionCode)
    {
        // hack: no real method of identifying if the error is max request exceeded as 
        // it is treated as a timeout exception
        if (http.StackTrace.Contains("GetEntireRawContent"))
        {
            // MAX REQUEST HAS BEEN EXCEEDED
            return true;
        }
    }

    return false;
}

2
ขอบคุณ OnError ไม่ทำงาน แต่ Application_Error ทำ จริงๆแล้วเรามีตัวจัดการสำหรับสิ่งนี้ แต่มีคนปิดมันไว้ในโค้ด
Marcus L

สองปีที่แล้ว แต่ฉันก็ยังอยากถามว่าตอนนี้ใช้ได้ดีไหม การเปรียบเทียบสตริงของ 'GetEntireRawContent' ทำงานได้ดีหรือไม่ ฉันไม่คิดว่านี่เป็นปัญหาการหมดเวลา มีใครยืนชี้ให้ฉันดูไม่ปิดบังเกี่ยวกับเรื่องนี้บ้าง?
Elaine

@Elaine ใช่เทคนิคนี้ยังคงใช้ได้กับ ASP.Net 4.0 หากคุณพยายามอัปโหลดคำขอที่ยาวกว่า ASP.Net ความยาวสูงสุดของคำขอจะแสดง HttpException พร้อมรหัสการหมดเวลา เข้าไปดูใน System.Web.HttpRequest.GetEntireRawContent () โดยใช้ตัวสะท้อนแสง
Damien McGivern

12
@ sam-rueby ฉันไม่ต้องการตอบกลับข้อความแสดงข้อผิดพลาดของสตริงที่อาจเปลี่ยนแปลงได้เนื่องจากการแปล
Damien McGivern

4
สำหรับ. NET 4.0 ขึ้นไปมีวิธีที่ดีกว่าในการระบุว่าเกินขนาดคำขอสูงสุดหรือไม่ คุณสามารถตรวจสอบเงื่อนไขนี้สำหรับ HttpException: httpException.WebEventCode == WebEventCodes.RuntimeErrorPostTooLarge- โดยใช้ System.Web.Management.WebEventCodes
mco

58

ดังที่ GateKiller กล่าวว่าคุณต้องเปลี่ยน maxRequestLength คุณอาจต้องเปลี่ยน ExecutionTimeout ในกรณีที่ความเร็วในการอัพโหลดช้าเกินไป โปรดทราบว่าคุณไม่ต้องการให้การตั้งค่าเหล่านี้ใหญ่เกินไปมิฉะนั้นคุณจะเปิดรับการโจมตีด้วย DOS

ค่าเริ่มต้นสำหรับการดำเนินการหมดเวลาคือ 360 วินาทีหรือ 6 นาที

คุณสามารถเปลี่ยน maxRequestLength และ executionTimeout กับhttpRuntime องค์ประกอบ

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.web>
        <httpRuntime maxRequestLength="102400" executionTimeout="1200" />
    </system.web>
</configuration>

แก้ไข:

หากคุณต้องการจัดการกับข้อยกเว้นไม่ว่าจะเป็นไปตามที่ระบุไว้แล้วก็ตามคุณจะต้องจัดการใน Global.asax นี่คือการเชื่อมโยงไปยังตัวอย่างรหัส


2
ขอบคุณสำหรับการตอบกลับ แต่อย่างที่ฉันพูดในความคิดเห็นต่อคำตอบของ GK สิ่งนี้ไม่ได้ช่วยแก้ปัญหาของฉันได้จริงๆ ไม่ใช่ปัญหาการหมดเวลาเช่นกันเนื่องจากข้อยกเว้นจะเกิดขึ้นทันที ฉันจะแก้ไขคำถามเพื่อให้ชัดเจนยิ่งขึ้น
Marcus L

4
ตัวอย่างโค้ด url ชี้ไปยังหน้าที่ไม่พร้อมใช้งาน ... มีใครแก้ไขได้ไหม
deostroll

20

คุณสามารถแก้ปัญหานี้ได้โดยเพิ่มความยาวคำขอสูงสุดใน web.config ของคุณ:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.web>
        <httpRuntime maxRequestLength="102400" />
    </system.web>
</configuration>

ตัวอย่างด้านบนเป็นขีด จำกัด 100Mb


18
ใช่และไม่. คุณเพิ่มขีด จำกัด ไปอีก แต่มันไม่ได้จัดการกับข้อยกเว้นจริงๆ คุณจะยังคงพบปัญหาเดิมหากมีคนพยายามอัปโหลด 101+ Mb ขีด จำกัด จริงๆต้องอยู่ที่ 5 Mb
Marcus L

10

หากคุณต้องการการตรวจสอบความถูกต้องฝั่งไคลเอ็นต์เพื่อให้คุณไม่จำเป็นต้องทิ้งข้อยกเว้นคุณสามารถลองใช้การตรวจสอบขนาดไฟล์ฝั่งไคลเอ็นต์ได้

หมายเหตุ: ใช้ได้เฉพาะในเบราว์เซอร์ที่รองรับ HTML5 http://www.html5rocks.com/en/tutorials/file/dndfiles/

<form id="FormID" action="post" name="FormID">
    <input id="target" name="target" class="target" type="file" />
</form>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" type="text/javascript"></script>

<script type="text/javascript" language="javascript">

    $('.target').change(function () {

        if (typeof FileReader !== "undefined") {
            var size = document.getElementById('target').files[0].size;
            // check file size

            if (size > 100000) {

                $(this).val("");

            }
        }

    });

</script>


9

สวัสดีวิธีแก้ปัญหาที่ Damien McGivern กล่าวถึงทำงานบน IIS6 เท่านั้น

ไม่ทำงานบน IIS7 และ ASP.NET Development Server ฉันได้รับหน้าที่แสดง "404 - ไม่พบไฟล์หรือไดเรกทอรี"

ความคิดใด ๆ ?

แก้ไข:

เข้าใจแล้ว ... โซลูชันนี้ยังใช้ไม่ได้กับ ASP.NET Development Server แต่ฉันได้รับเหตุผลว่าทำไมมันถึงไม่ทำงานบน IIS7 ในกรณีของฉัน

เหตุผลคือ IIS7 มีการสแกนคำขอในตัวซึ่งกำหนดขีด จำกัด ไฟล์อัปโหลดซึ่งมีค่าเริ่มต้นเป็น 30000000 ไบต์ (ซึ่งน้อยกว่าเล็กน้อยที่ 30MB)

และฉันพยายามอัปโหลดไฟล์ขนาด 100 MB เพื่อทดสอบโซลูชันที่ Damien McGivern กล่าวถึง (ด้วย maxRequestLength = "10240" เช่น 10MB ใน web.config) ตอนนี้หากฉันอัปโหลดไฟล์ขนาด> 10MB และ <30 MB หน้านั้นจะถูกเปลี่ยนเส้นทางไปยังหน้าข้อผิดพลาดที่ระบุ แต่ถ้าขนาดไฟล์> 30MB จะแสดงหน้าข้อผิดพลาดในตัวที่น่าเกลียดซึ่งแสดง "404 - ไม่พบไฟล์หรือไดเร็กทอรี"

ดังนั้นเพื่อหลีกเลี่ยงปัญหานี้คุณต้องเพิ่มสูงสุด ความยาวเนื้อหาคำขอที่อนุญาตสำหรับเว็บไซต์ของคุณใน IIS7 ที่สามารถทำได้โดยใช้คำสั่งต่อไปนี้

appcmd set config "SiteName" -section:requestFiltering -requestLimits.maxAllowedContentLength:209715200 -commitpath:apphost

ฉันตั้งค่าสูงสุดไว้แล้ว ความยาวเนื้อหาถึง 200MB

หลังจากทำการตั้งค่านี้หน้าจะถูกเปลี่ยนเส้นทางไปยังหน้าข้อผิดพลาดของฉันอย่างประสบความสำเร็จเมื่อฉันพยายามอัปโหลดไฟล์ขนาด 100MB

อ้างอิงhttp://weblogs.asp.net/jgalloway/archive/2008/01/08/large-file-uploads-in-asp-net.aspxสำหรับรายละเอียดเพิ่มเติม


ขออภัย! ฉันได้เพิ่มคำถามของฉันเป็นคำตอบฉันไม่รู้วิธีเพิ่มความคิดเห็นในโพสต์ที่มีอยู่
Vinod T. Patil

1
คุณเพียงแค่ต้องการตัวแทนเพิ่มเติม เพื่อแสดงความคิดเห็นโพสต์ ดูคำถามที่พบบ่อยสำหรับรายละเอียดเพิ่มเติมเกี่ยวกับสิ่งที่คุณสามารถ / ไม่สามารถทำได้กับตัวแทนปัจจุบันของคุณ
สุข

7

นี่เป็นอีกทางเลือกหนึ่งที่ไม่เกี่ยวข้องกับ "แฮ็ก" ใด ๆ แต่ต้องใช้ ASP.NET 4.0 หรือใหม่กว่า:

//Global.asax
private void Application_Error(object sender, EventArgs e)
{
    var ex = Server.GetLastError();
    var httpException = ex as HttpException ?? ex.InnerException as HttpException;
    if(httpException == null) return;

    if(httpException.WebEventCode == WebEventCodes.RuntimeErrorPostTooLarge)
    {
        //handle the error
        Response.Write("Sorry, file is too big"); //show this message for instance
    }
}

4

วิธีหนึ่งในการทำเช่นนี้คือกำหนดขนาดสูงสุดใน web.config ตามที่ระบุไว้ข้างต้นเช่น

<system.web>         
    <httpRuntime maxRequestLength="102400" />     
</system.web>

จากนั้นเมื่อคุณจัดการเหตุการณ์อัปโหลดให้ตรวจสอบขนาดและหากเกินจำนวนที่กำหนดคุณสามารถดักจับได้เช่น

protected void btnUploadImage_OnClick(object sender, EventArgs e)
{
    if (fil.FileBytes.Length > 51200)
    {
         TextBoxMsg.Text = "file size must be less than 50KB";
    }
}

1
วิธีนี้ใช้ไม่ได้ เหตุการณ์คลิกจะไม่ถูกทริกเกอร์ ข้อยกเว้นเกิดขึ้นก่อน
Lombas


3

ใน IIS 7 ขึ้นไป:

ไฟล์ web.config:

<system.webServer>
  <security >
    <requestFiltering>
      <requestLimits maxAllowedContentLength="[Size In Bytes]" />
    </requestFiltering>
  </security>
</system.webServer>

จากนั้นคุณสามารถเช็คอินรหัสหลังได้ดังนี้:

If FileUpload1.PostedFile.ContentLength > 2097152 Then ' (2097152 = 2 Mb)
  ' Exceeded the 2 Mb limit
  ' Do something
End If

ตรวจสอบให้แน่ใจว่า [Size In Bytes] ใน web.config นั้นใหญ่กว่าขนาดไฟล์ที่คุณต้องการอัปโหลดคุณจะไม่ได้รับข้อผิดพลาด 404 จากนั้นคุณสามารถตรวจสอบขนาดไฟล์ในโค้ดด้านหลังโดยใช้ ContentLength ซึ่งจะดีกว่ามาก


2

ดังที่คุณทราบความยาวคำขอสูงสุดถูกกำหนดไว้ในสองตำแหน่ง

  1. maxRequestLength - ควบคุมที่ระดับแอป ASP.NET
  2. maxAllowedContentLength- อยู่ภายใต้การ<system.webServer>ควบคุมที่ระดับ IIS

กรณีแรกครอบคลุมโดยคำตอบอื่น ๆ สำหรับคำถามนี้

ในการจับTHE SECOND ONEคุณต้องทำสิ่งนี้ใน global.asax:

protected void Application_EndRequest(object sender, EventArgs e)
{
    //check for the "file is too big" exception if thrown at the IIS level
    if (Response.StatusCode == 404 && Response.SubStatusCode == 13)
    {
        Response.Write("Too big a file"); //just an example
        Response.End();
    }
}

1

หลังแท็ก

<security>
     <requestFiltering>
         <requestLimits maxAllowedContentLength="4500000" />
     </requestFiltering>
</security>

เพิ่มแท็กต่อไปนี้

 <httpErrors errorMode="Custom" existingResponse="Replace">
  <remove statusCode="404" subStatusCode="13" />
  <error statusCode="404" subStatusCode="13" prefixLanguageFilePath="" path="http://localhost/ErrorPage.aspx" responseMode="Redirect" />
</httpErrors>

คุณสามารถเพิ่ม URL ในหน้าข้อผิดพลาด ...


0

คุณสามารถแก้ปัญหานี้ได้โดยเพิ่มความยาวคำขอสูงสุดและเวลาดำเนินการใน web.config ของคุณ:

- โปรดชี้แจงเวลาการดำเนินการสูงสุดที่ขูดออกแล้ว 1200

<?xml version="1.0" encoding="utf-8"?> <configuration> <system.web> <httpRuntime maxRequestLength="102400" executionTimeout="1200" /> </system.web> </configuration>

0

แล้วไปจับที่งาน EndRequest ได้อย่างไร?

protected void Application_EndRequest(object sender, EventArgs e)
    {
        HttpRequest request = HttpContext.Current.Request;
        HttpResponse response = HttpContext.Current.Response;
        if ((request.HttpMethod == "POST") &&
            (response.StatusCode == 404 && response.SubStatusCode == 13))
        {
            // Clear the response header but do not clear errors and
            // transfer back to requesting page to handle error
            response.ClearHeaders();
            HttpContext.Current.Server.Transfer(request.AppRelativeCurrentExecutionFilePath);
        }
    }

0

สามารถตรวจสอบได้ทาง:

        var httpException = ex as HttpException;
        if (httpException != null)
        {
            if (httpException.WebEventCode == System.Web.Management.WebEventCodes.RuntimeErrorPostTooLarge)
            {
                // Request too large

                return;

            }
        }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.