zoukankan      html  css  js  c++  java
  • ASP.NET 上传大文件(原创)

    问题描述

    需要在网站中上传文件,但是当文件大小太大的时候IIS会拒绝连接,导致用户看到不友好的错误界面。

    解决方法

    1.服务器端处理

      在globle.asax中的protected void Application_Error(object sender, EventArgs e)函数中处理错误

      

        public class Global : System.Web.HttpApplication
        {
            static List<string[]> options;
            static Global(){
                var mlstr = WebConfigurationManager.AppSettings.Get("MaxRequestLength");
                if (string.IsNullOrEmpty(mlstr)) options = null;
                else
                {
                    try
                    {
                        var optionstr = mlstr.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
                        options = new List<string[]>();
                        optionstr.ToList().ForEach(e => options.Add(e.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries)));
                    }
                    catch(Exception e) { options = null; }
                }
            }
    ...
            protected void Application_Error(object sender, EventArgs e)
            {
                
                if (Server.GetLastError().GetType() != typeof(HttpException)) return;
                if (options == null) return;
                var item = options.Find(i => i[0] == this.Request.Url.LocalPath);
                if (item == null) return;
    
                int maxRequestLength = 0;
                Int32.TryParse(item[1], out maxRequestLength);
    
                //This code is used to check the request length of the page and if the request length is greater than
                //MaxRequestLength then retrun to the same page with extra query string value action=exception
    
                HttpContext context = ((HttpApplication)sender).Context;
                if (context.Request.ContentLength > maxRequestLength)
                {
                    IServiceProvider provider = (IServiceProvider)context;
                    HttpWorkerRequest workerRequest = (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));
    
                    // Check if body contains data
                    if (workerRequest.HasEntityBody())
                    {
                        // get the total body length
                        int requestLength = workerRequest.GetTotalEntityBodyLength();
                        // Get the initial bytes loaded
                        int initialBytes = 0;
                        if (workerRequest.GetPreloadedEntityBody() != null)
                            initialBytes = workerRequest.GetPreloadedEntityBody().Length;
                        if (!workerRequest.IsEntireEntityBodyIsPreloaded())
                        {
                            byte[] buffer = new byte[512000];
                            // Set the received bytes to initial bytes before start reading
                            int receivedBytes = initialBytes;
                            while (requestLength - receivedBytes >= initialBytes)
                            {
                                // Read another set of bytes
                                initialBytes = workerRequest.ReadEntityBody(buffer, buffer.Length);
    
                                // Update the received bytes
                                receivedBytes += initialBytes;
                            }
                            initialBytes = workerRequest.ReadEntityBody(buffer, requestLength - receivedBytes);
                        }
                    }
                    //Redirect the user to the same page with querystring action=exception.
                    //Response.ClearContent();
                    //context.Server.ClearError();
                    context.Response.Redirect(this.Request.Url.LocalPath + "?" + item[2]);
                }
            }
    ...
    }
    View Code
    <appSettings>
        <add key="MaxRequestLength" value="/upload.ashx,100,errorcallback=upCallback"/>
      </appSettings>

    2.前端处理

      上传方式采用的是iframe仿ajax。因此考虑截获iframe的onload事件从而进行友好提示。

      但是经过测试:当服务器因连接长度过长断开连接时,firefox不会触发iframe的onload事件,因此该方法失败。

      http://src.chromium.org/svn/trunk/src/tools/measure_page_load_time/ff_ext/content/measure_page_load_time.js

      中第156行附近也说明了firefox没有好的截获connection reset事件的方式。

    3.其他

    其他诸如改变默认大小的方法不可取,因为无论多大,用户都可能选择超过你的设定。

    结论

    暂时采用方法一。如果firefox中可以截获connection reset事件,方法2明显优于方法1.

    因为在方法一种会将上传文件全部读取(并不保存),消耗服务器资源。

    原创于:http://www.cnblogs.com/errorx/

    转载请注明

  • 相关阅读:
    use paramiko to connect remote server and execute command
    protect golang source code
    adjust jedi vim to python2 and python3
    install vim plugin local file offline
    add swap file if you only have 1G RAM
    datatables hyperlink in td
    django rest framework custom json format
    【JAVA基础】网络编程
    【JAVA基础】多线程
    【JAVA基础】String类的概述和使用
  • 原文地址:https://www.cnblogs.com/errorx/p/3161773.html
Copyright © 2011-2022 走看看