• 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/

    转载请注明

  • 相关阅读:
    Jquery事件
    基础:装箱和拆箱...
    navicat编辑表的作用
    谷歌浏览器preview展示问题
    @Scheduled并行执行
    spring异步执行方法线程池的配置
    dubbo的ExceptionFilter异常处理
    dubbo异常处理
    idea设置启动jvm参数
    前后端分离走本地代码Charles的使用
  • 原文地址:https://www.cnblogs.com/errorx/p/3161773.html
Copyright © 2020-2023  润新知