• [导入]SunriseUpload.0.9.1的源码分析(三)


    在分析上传的数据时,这里用到了这样的一个函数:
      /// <summary>
      /// Get value from preloaded entity body. Identified by name.
      /// </summary>
      /// <param name="preloadedEntityBody"></param>
      /// <param name="name"></param>
      /// <returns></returns>
      private string AnalysePreloadedEntityBody(byte[] preloadedEntityBody, string name)
      {
       string val = string.Empty;
       string preloadedContent = Utils.GetContext().Request.ContentEncoding.GetString(preloadedEntityBody);

       if (preloadedContent.Length > 0)
       {
        int startIndex = ((preloadedContent.IndexOf(("name=\"" + name + "\"")) + 11) + name.Length);
        int endIndex = preloadedContent.IndexOf("\r\n", startIndex);
        val = preloadedContent.Substring(startIndex, (endIndex - startIndex));
       }

       return val;
      }
    输出的结果让我郁闷:(输出的是startIndex和endIndex及函数返回值)
    11/2/2005 10:33:55 AM 5ea  
    11/2/2005 10:33:55 AM a
    11/2/2005 10:33:55 AM :in test file.
    还是先不管它的输出结果,分析代码吧。
    看了半天也不明白这个函数是在干什么,测试输出结果让我很费解,这个函数在一次申请过程中调用过两次?
    ......输出的是startIndex和endIndex及函数返回值)
    11/2/2005 10:55:09 AM 39 start
    11/2/2005 10:55:09 AM 41 end
    11/2/2005 10:55:09 AM 02 var
    ......
    11/2/2005 10:55:09 AM 41
    11/2/2005 10:55:09 AM 41
    11/2/2005 10:55:09 AM 
    我试着上传一个很大的文件,然后得到以下信息:
    11/2/2005 11:03:27 AM 39
    11/2/2005 11:03:27 AM 43
    11/2/2005 11:03:27 AM 0266

    11/2/2005 11:03:28 AM 41
    11/2/2005 11:03:28 AM 43
    11/2/2005 11:03:28 AM 66

    11/2/2005 11:04:18 AM 39
    11/2/2005 11:04:18 AM 43
    11/2/2005 11:04:18 AM 0212

    11/2/2005 11:04:18 AM 41
    11/2/2005 11:04:18 AM 43
    11/2/2005 11:04:18 AM 12
    可以这样分析吧:如果再一次请求过程中,提交了所有的数据,那么这个函数只被调用两次(我不知道不是上传文件都会有两次请求?)
    否则会么多次请求,而且在上传没有结束之前,这个函数返回值都不为空。。。。。我也只能分析这些了。

    看调用它的主函数的处理方法吧:
    string uploadGuid = this.AnalysePreloadedEntityBody(preloadedEntityBody, "Sunrise_Web_Upload_UploadGUID");
    if (uploadGuid != string.Empty)
    {
    application.Context.Items.Add("Sunrise_Web_Upload_UploadGUID", uploadGuid);
    }
    当然,在第一次调用this.AnalysePreloadedEntityBody的时候,返回不为空,所以会在application里添加一个Item
    而里面记录的就是我们this.AnalysePreloadedEntityBody返回的值。。。。

    string uploadFolder = this.AnalysePreloadedEntityBody(preloadedEntityBody, "Sunrise_Web_Upload_UploadFolder");
    这里是第二次调用该方法,用于取回上传文件的临时路径。应该明白了,this.AnalysePreloadedEntityBody用来分析和读取用户上传的一些数据。这里主要是分析一些参数。

    ArrayList readBody = new ArrayList();
    RequestStream preloadedStream = new RequestStream(preloadedEntityBody, boundaryData,
    null, RequestStream.FileStatus.Close, RequestStream.ReadStatus.NoRead, uploadFolder, isUploadFinished, application.Context, string.Empty);
    这里是它的一个核心类了。看看它的构造函数!
    核心在这个循环上了:
    while ((preloadPosition < preloadBytes.Length))
    代码太长,一下子还不好分析。。。郁闷中。。。。

    没有再向下分析代码了,理由是我目前对用户提交上来的内容还不清楚,不知道应该怎样处理用户提交上来的数据。因此决定自己先把前面的内容搞清楚,于是自己写了一个HttpModule来测试。
    经过这个模块的测试,终于对HTTP协议的请求有了一个全面的认识,当然这只是我自己推测的,至于对不对,那就不好说了。

    先看看我写的代码:

    using System;
    using System.Collections;
    using System.IO;
    using System.Reflection;
    using System.Text;
    using System.Web;
    using System.Xml;

    namespace WebbTest
    {
     /// <summary>
     /// Summary description for UploadTest.
     /// </summary>
     public class HttpModuleTest : IHttpModule
     {
      private System.DateTime m_startTime;

      public HttpModuleTest()
      {
       //
       // TODO: Add constructor logic here
       //
       m_startTime  = System.DateTime.Now;
       WebbSystem.TraceMsg("Construct the HttpModule.");
      }

      public void Dispose()
      {
      }

      #region initialization function
      /// <summary>
      ///
      /// </summary>
      /// <param name="m_application"></param>
      public void Init(System.Web.HttpApplication m_application)
      {
       m_application.BeginRequest += new EventHandler(m_application_BeginRequest);
       m_application.EndRequest += new EventHandler(m_application_EndRequest);
       m_application.Error   += new EventHandler(m_application_Error);
       TimeSpan m_timeSpan   = System.DateTime.Now.Subtract(m_startTime);
       WebbSystem.TraceMsg("Init in the HttpModule."+m_timeSpan.TotalSeconds.ToString());
      }
      #endregion

      #region Event functions
      /// <summary>
      ///
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      private void m_application_BeginRequest(object sender, EventArgs e)
      {
       #region debug message
       TimeSpan m_timeSpan   = System.DateTime.Now.Subtract(m_startTime);
       WebbSystem.TraceMsg("m_application_BeginRequest in the HttpModule."+m_timeSpan.TotalSeconds.ToString());
       #endregion

       HttpApplication m_application  = (sender as HttpApplication);
       HttpWorkerRequest m_workerRequest = GetWorkerRequest();
       //WebbSystem.TraceMsg(m_application.Request.ContentType.ToString());

       byte[] m_preLoadedData    = m_workerRequest.GetPreloadedEntityBody();
    //   Encoding targetEncoding;
    //   targetEncoding.EncodingName   = Encoding.UTF8;
       if(m_preLoadedData!=null)
       {
        string m_temp      = Encoding.UTF8.GetString(m_preLoadedData);
        WebbSystem.TraceMsg(m_temp);
       }
      }

      private void m_application_EndRequest(object sender, EventArgs e)
      {
       TimeSpan m_timeSpan   = System.DateTime.Now.Subtract(m_startTime);
       WebbSystem.TraceMsg("m_application_EndRequest in the HttpModule."+m_timeSpan.TotalSeconds.ToString());
       //Do some thing to release resouce.
       HttpApplication application = (sender as HttpApplication);
       application.Context.Items.Clear();

      }

      private void m_application_Error(object sender, EventArgs e)
      {
       TimeSpan m_timeSpan   = System.DateTime.Now.Subtract(m_startTime);
       WebbSystem.TraceMsg("Error in the HttpModule."+m_timeSpan.TotalSeconds.ToString());
       //Do some thing to release resouce.
      }
      #endregion

      #region Assistant functions
      private HttpWorkerRequest GetWorkerRequest()
      {
       IServiceProvider provider = HttpContext.Current;
       return ((HttpWorkerRequest) provider.GetService(typeof (HttpWorkerRequest)));
      }
      #endregion
     }
    }
    其中WebbSystem.TraceMsg是一个向文本文件中写入记录的辅助函数,用于查看结果。最后我得到的内容:
    当第一次请求的时候:
    11/2/2005 2:47:16 PM m_application_BeginRequest in the HttpModule.59.28125
    11/2/2005 2:47:16 PM 
    11/2/2005 2:47:16 PM m_application_EndRequest in the HttpModule.59.28125

    点击一个button后的结果,当然我这个页面是multipart/form-data方法的
    11/2/2005 2:46:30 PM m_application_BeginRequest in the HttpModule.13.71875
    11/2/2005 2:46:30 PM multipart/form-data; boundary=---------------------------7d51a51e25012c
    11/2/2005 2:46:30 PM -----------------------------7d51a51e25012c
    Content-Disposition: form-data; name="__VIEWSTATE"

    dDwtNTMwNzcxMzI0Ozs+eJ8D5aYupVVxznfxhPOz74IwJsk=
    -----------------------------7d51a51e25012c
    Content-Disposition: form-data; name="m_file"; filename=""
    Content-Type: application/octet-stream


    -----------------------------7d51a51e25012c
    Content-Disposition: form-data; name="Button1"

    Button
    -----------------------------7d51a51e25012c--

    11/2/2005 2:46:30 PM m_application_EndRequest in the HttpModule.13.71875
    只要我不关闭浏览器,那么boundary的值都是一定的,也就是说
    contenttype给出了请求的格式:multipart/form-data; boundary=---------------------------7d51a51e25012c
    就是说:这是一个文件上传请求,用---------------------------7d51a51e25012c来分隔数据,所以上而的数据就是那样的了。
    于是,在每次处理提交上来的数据的时候,一定要先处理conetntTpye然后再来通过它来处理上传的数据。最后用--来结束上传数据。
    数据名与内容用 "\r\n\r\n"来分隔。好了,下面我自己来写一个函数来处理上传的数据。


    文章来源:http://computer.mblogger.cn/wucountry/posts/48499.aspx
    ================================
      /\_/\                        
     (=^o^=)  Wu.Country@侠缘      
     (~)@(~)  一辈子,用心做一件事!
    --------------------------------
      学而不思则罔,思而不学则怠!  
    ================================
  • 相关阅读:
    阿里P8推荐的SpingBoot学习手册+Git开源项目实践分享,还不收藏
    阿里P8划重点:JVM+Spring+Mybatis+多线程高并发源码你必须会
    一线大厂工程师推荐:Mysql、Springboot、JVM、Spring等面试合集
    GitHub标星120K+的JDK并发编程指南,连续霸榜GitHub终于开源了
    腾讯被指劝退高龄员工,华为百度也在优化,互联网35岁+该怎么办
    天猫面试官硬核推荐:Dubbo+ES+JVM+多线程/高并发+消息队列
    多线程与高并发:金九银十跳槽季面试必须要掌握的硬核涨薪技能
    纯干货,源码6步曲,带你解析完整的ThreadPoolExecutor
    今日总结
    今日头条技术架构分析
  • 原文地址:https://www.cnblogs.com/WuCountry/p/305657.html
Copyright © 2020-2023  润新知