Menangkap "Panjang permintaan maksimum terlampaui"

112

Saya sedang menulis fungsi unggah, dan mengalami masalah saat menangkap "System.Web.HttpException: Panjang permintaan maksimum terlampaui" dengan file lebih besar dari ukuran maksimal yang ditentukan httpRuntimedi web.config (ukuran maks disetel ke 5120). Saya menggunakan sederhana <input>untuk file tersebut.

Masalahnya adalah bahwa pengecualian dilemparkan sebelum peristiwa klik tombol unggah, dan pengecualian terjadi sebelum kode saya dijalankan. Jadi, bagaimana cara menangkap dan menangani pengecualian?

EDIT: Pengecualian dilemparkan secara instan, jadi saya cukup yakin ini bukan masalah batas waktu karena koneksi yang lambat.

Marcus L.
sumber
5
Apakah ada yang mencoba ini dengan MVC? Saya tampaknya dapat menangkap pengecualian dengan cara yang benar, tetapi saya tidak dapat menghentikannya: setiap kali saya mencoba membuat laman kesalahan, pengecualian yang sama terjadi.
Andy
Pesan kesalahan ini dilemparkan oleh IIS sebelum mencapai pengontrol. Untuk memberi tahu pengguna bahwa file tersebut melebihi batas unggahan maksimum (ditetapkan di web-config Anda), Anda dapat langsung memvalidasi ukuran file melalui JS dengan acara onchange. Misalnya di <input type="file" id="upload" name="upload" onchange="showFileSize();" />dalam showFileSize(), Anda dapat menampilkan pesan kesalahan berdasarkan ukuran file Anda melalui var input = document.getElementById("upload"); var file = input.files[0];dan menambahkan tag html.
Alfred Wallace

Jawaban:

97

Sayangnya, tidak ada cara mudah untuk menangkap pengecualian seperti itu. Apa yang saya lakukan adalah mengganti metode OnError di tingkat halaman atau Application_Error di global.asax, lalu periksa apakah itu kegagalan Permintaan Maks dan, jika demikian, transfer ke halaman kesalahan.

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");
    }
}

Ini peretasan tetapi kode di bawah ini berfungsi untuk saya

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;
}
Damien McGivern
sumber
2
Terima kasih. OnError tidak berfungsi, tetapi Application_Error berhasil. Kami sebenarnya memiliki penangan untuk ini, tetapi seseorang telah mematikannya di kode.
Marcus L
bahkan dua tahun yang lalu, tetapi saya masih ingin bertanya apakah ini berfungsi dengan baik sampai sekarang? apakah perbandingan string 'GetEntireRawContent' berfungsi dengan baik? Saya tidak berpikir ini adalah masalah batas waktu. apakah ada orang yang menonjol karena mengarahkan saya ke suatu tempat yang tidak jelas tentang ini?
Elaine
@Elaine ya teknik ini masih berfungsi dengan ASP.Net 4.0. Jika Anda mencoba mengunggah permintaan yang lebih besar dari panjang permintaan maksimum ASP.Net akan melontarkan HttpException dengan kode waktu tunggu. Lihat di System.Web.HttpRequest.GetEntireRawContent () menggunakan reflektor.
Damien McGivern
12
@ sam-rueby Saya tidak ingin membalas pesan kesalahan string yang dapat berubah karena pelokalan.
Damien McGivern
4
Untuk .NET 4.0 dan yang lebih baru, ada cara yang lebih baik untuk mengidentifikasi apakah ukuran permintaan maks terlampaui. Anda dapat memeriksa kondisi ini untuk HttpException: httpException.WebEventCode == WebEventCodes.RuntimeErrorPostTooLarge- menggunakan System.Web.Management.WebEventCodes
mco
58

Seperti yang dikatakan GateKiller, Anda perlu mengubah maxRequestLength. Anda mungkin juga perlu mengubah executionTimeout jika kecepatan upload terlalu lambat. Perhatikan bahwa Anda tidak ingin salah satu dari pengaturan ini menjadi terlalu besar jika tidak Anda akan terbuka untuk serangan DOS.

Default untuk executionTimeout adalah 360 detik atau 6 menit.

Anda dapat mengubah maxRequestLength dan executionTimeout dengan Elemen httpRuntime .

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

EDIT:

Jika Anda ingin menangani pengecualian tersebut seperti yang telah dinyatakan, Anda harus menanganinya di Global.asax. Berikut tautan ke contoh kode .

Jonathan Parker
sumber
2
Terima kasih atas balasan Anda, tetapi seperti yang saya katakan dalam komentar saya untuk jawaban GK ini tidak benar-benar menyelesaikan masalah saya. Ini juga bukan masalah batas waktu, karena pengecualian dilemparkan secara instan. Saya akan mengedit pertanyaan untuk membuatnya lebih jelas.
Marcus L
4
Contoh kode url menunjuk ke halaman yang tidak tersedia ... adakah yang bisa memperbaikinya?
batalkan pendaftaran
20

Anda dapat menyelesaikan ini dengan meningkatkan panjang permintaan maksimum di web.config Anda:

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

Contoh di atas adalah untuk batas 100Mb.

GateKiller
sumber
18
Iya dan tidak. Anda mendorong batas lebih jauh, tetapi itu tidak benar-benar menangani pengecualian. Anda masih akan mendapatkan masalah yang sama jika seseorang mencoba mengunggah 101+ Mb. Batasnya harus 5 Mb.
Marcus L
10

Jika Anda menginginkan validasi sisi klien juga sehingga Anda tidak perlu membuang pengecualian, Anda dapat mencoba menerapkan validasi ukuran file sisi klien.

Catatan: Ini hanya berfungsi di browser yang mendukung 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>

Andrew
sumber
9

Hai solusi yang disebutkan oleh Damien McGivern, Hanya berfungsi di IIS6,

Itu tidak bekerja di IIS7 dan ASP.NET Development Server. Saya mendapatkan halaman yang menampilkan "404 - File atau direktori tidak ditemukan."

Ada ide?

EDIT:

Mengerti ... Solusi ini masih tidak berfungsi di Server Pengembangan ASP.NET, tetapi saya mendapat alasan mengapa itu tidak berfungsi di IIS7 dalam kasus saya.

Alasannya adalah IIS7 memiliki pemindaian permintaan bawaan yang memberlakukan batas file unggahan yang defaultnya adalah 30000000 byte (yang sedikit kurang dari 30MB).

Dan saya mencoba mengunggah file berukuran 100 MB untuk menguji solusi yang disebutkan oleh Damien McGivern (dengan maxRequestLength = "10240" yaitu 10MB di web.config). Sekarang, Jika saya mengunggah file dengan ukuran> 10MB dan <30 MB maka halaman tersebut dialihkan ke halaman kesalahan yang ditentukan. Tetapi jika ukuran file> 30MB maka itu menunjukkan halaman kesalahan built-in jelek yang menampilkan "404 - File atau direktori tidak ditemukan."

Jadi, untuk menghindari hal ini, Anda harus meningkatkan maks. diizinkan meminta panjang konten untuk situs web Anda di IIS7. Itu bisa dilakukan dengan menggunakan perintah berikut,

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

Saya telah menetapkan maks. panjang konten hingga 200MB.

Setelah melakukan pengaturan ini, halaman berhasil dialihkan ke halaman kesalahan saya ketika saya mencoba mengunggah file berukuran 100MB

Lihat, http://weblogs.asp.net/jgalloway/archive/2008/01/08/large-file-uploads-in-asp-net.aspx untuk lebih jelasnya.

Vinod T. Patil
sumber
Maaf! Saya telah menambahkan kueri saya sebagai Jawaban, saya tidak tahu bagaimana menambahkan komentar ke posting yang ada.
Vinod T. Patil
1
Anda hanya perlu lebih banyak perwakilan. untuk mengomentari postingan. Lihat faq untuk detail lebih lanjut tentang apa yang bisa / tidak bisa Anda lakukan dengan perwakilan Anda saat ini.
slaphappy
7

Berikut cara alternatif, yang tidak melibatkan "peretasan", tetapi membutuhkan ASP.NET 4.0 atau yang lebih baru:

//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
    }
}
Serge Shultz
sumber
4

Salah satu cara untuk melakukan ini adalah dengan mengatur ukuran maksimum di web.config seperti yang telah disebutkan di atas misalnya

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

kemudian ketika Anda menangani acara unggahan, periksa ukurannya dan jika melebihi jumlah tertentu, Anda dapat menjebaknya misalnya

protected void btnUploadImage_OnClick(object sender, EventArgs e)
{
    if (fil.FileBytes.Length > 51200)
    {
         TextBoxMsg.Text = "file size must be less than 50KB";
    }
}
BaggieBoy
sumber
1
Ini tidak berhasil. Peristiwa klik tidak pernah dipicu. Pengecualian terjadi sebelumnya.
Lombas
3

Di IIS 7 dan seterusnya:

file web.config:

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

Anda kemudian dapat memeriksa kode di belakang, seperti:

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

Pastikan saja [Size In Bytes] di web.config lebih besar dari ukuran file yang ingin anda upload maka anda tidak akan mendapatkan error 404. Anda kemudian dapat memeriksa ukuran file dalam kode di belakang menggunakan ContentLength yang akan jauh lebih baik

Walery Strauch
sumber
2

Seperti yang mungkin Anda ketahui, panjang permintaan maksimum dikonfigurasi di DUA tempat.

  1. maxRequestLength - dikontrol di tingkat aplikasi ASP.NET
  2. maxAllowedContentLength- di bawah <system.webServer>, dikontrol di tingkat IIS

Kasus pertama tercakup dalam jawaban lain untuk pertanyaan ini.

Untuk menangkap YANG KEDUA Anda perlu melakukan ini di 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();
    }
}
jazzcat
sumber
1

Setelah tag

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

tambahkan tag berikut

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

Anda dapat menambahkan Url ke halaman kesalahan ...

Diego
sumber
0

Anda dapat menyelesaikan ini dengan meningkatkan panjang permintaan maksimum dan waktu eksekusi di web.config Anda:

-Harap Perjelas waktu eksekusi maksimum keluar parutan kemudian 1200

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

Bagaimana kalau menangkapnya di acara 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);
        }
    }
Khoa Tran
sumber
0

Ini dapat diperiksa melalui:

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

                return;

            }
        }
Raghav
sumber