Asp.NET大文件上传组件开发总结(四)---封送数据给Asp.NET页面

     这个功能主要是为了不影响Asp.NET的处理模型,将请求中除上传的文件内容外的其它正常请求内容继续发送到Asp.NET页面处理。

    我们通过分析HttpRequest对象的GetEntireRawContent()方法在读取数据,并且发现这个方法在读取数据时,是将数据赋值到了_rawContent属性,所以我们只要能把处理后的数据赋值给HttpRequest对象的_rawContent属性,即可封送数据给Asp.NET页面。同时,由于我们改写了请求内容,所以HttpRequest_contentLength也应当改写。

    由于这些属性方式是私有的,我们不能直接访问,所以我们必须采用反射的方法给属性赋值。代码如下:

 private void InjectTextParts(HttpRequest request, byte[] textParts)
        
{
            BindingFlags flags1 
= BindingFlags.NonPublic | BindingFlags.Instance;
            Type type1 
= request.GetType();
            FieldInfo info1 
= type1.GetField("_rawContent", flags1);
            FieldInfo info2 
= type1.GetField("_contentLength", flags1);
            
            
if ((info1 != null&& (info2 != null))
            
{
                Assembly web 
= Assembly.GetAssembly(typeof(HttpRequest));
                Type hraw 
= web.GetType("System.Web.HttpRawUploadedContent");
                
object[] argList = new object[2];
                argList[
0= textParts.Length + 1024;
                argList[
1= textParts.Length;

                CultureInfo currCulture 
= CultureInfo.CurrentCulture;
                
object httpRawUploadedContent = Activator.CreateInstance(hraw,
                                                                         BindingFlags.NonPublic 
| BindingFlags.Instance,
                                                                         
null,
                                                                         argList,
                                                                         currCulture,
                                                                         
null);

               Type contentType 
= httpRawUploadedContent.GetType();

               FieldInfo dataField 
= contentType.GetField("_data", flags1);
               dataField.SetValue(httpRawUploadedContent, textParts);

               FieldInfo lengthField 
= contentType.GetField("_length", flags1);
               lengthField.SetValue(httpRawUploadedContent, textParts.Length);

               FieldInfo fileThresholdField 
= contentType.GetField("_fileThreshold", flags1);
               fileThresholdField.SetValue(httpRawUploadedContent, textParts.Length 
+ 1024);

               info1.SetValue(request, httpRawUploadedContent);
               info2.SetValue(request, textParts.Length);
            }

        }



    在这里,在将代码用到
NET2.0时,遇到了问题。因为在NET1.1时,HttpRequest_rawContent属性是一个byte[]类型,但到了NET2.0,这个属性变成了HttpRawUploadedContent类型的对象,出现了赋值失败。通过查看HttpRawUploadedContent反射代码,发现原来这个类是为了将过大的请求内容写到磁盘文件中。没办法,我只有创建这个类的实例后再赋值给HttpRequest_rawContent属性。这下能上传文件了,可是,Asp.NET页面的控件值全部丢失了,数据没有有效的封送到页面。嘿嘿,这里正好发挥我刚学会的一项技术---调试框架源码。于是从GetEntireRawContent()方法一路跟踪下去,发现是由于HttpRawUploadedContent对象的_length属性为零,导致HttpRequest对象认为没有有效数据而没有分析数据。导致通过HttpRequestParams属性和Forms数据不能访问到请求内容。给这两个数据赋值后,哈!哈!一切顺利。上传过程全部结束!
由于NET2.0代码只是初步完成,等我在作进一步测试后,将在写完这部分总结后,提供给大家下载。
标签: Asp.NET

posted on 2008-05-16 14:27 巴山 阅读(3687) 评论(9) 编辑 收藏

评论

#1楼  回复 引用 查看   

楼主辛苦了!
2008-05-16 14:52 | 亦续缘      

#2楼  回复 引用   

不错,似乎比SlickUpload,AspNetUpload等涉及Asp.NET底层更深。
2008-05-16 18:01 | XmArO[未注册用户]

#3楼  回复 引用 查看   

学习~
2008-05-16 18:33 | 飘遥      

#4楼  回复 引用 查看   

关注。。。期待下面的文章
2008-05-17 11:55 | ppchen(陈荣林)      

#5楼  回复 引用 查看   

//我想问一下
contentType.GetField("_completed", flags1).SetValue(httpRawUploadedContent, true);

//_completed是起什么作用

 //我在2.0下编译,不加上这一句就会出错。
 /*
[InvalidOperationException: 对象的当前状态使该操作无效。]
System.Web.HttpRawUploadedContent.get_Item(Int32 index) +3325637
System.Web.HttpMultipartContentTemplateParser.GetNextLine() +30
System.Web.HttpMultipartContentTemplateParser.ParseIntoElementList() +15
System.Web.HttpMultipartContentTemplateParser.Parse(HttpRawUploadedContent data, Int32 length, Byte[] boundary, Encoding encoding) +45
System.Web.HttpRequest.GetMultipartContent() +100
System.Web.HttpRequest.FillInFormCollection() +222
System.Web.HttpRequest.get_Form() +65
System.Web.HttpRequest.get_HasForm() +3309630
System.Web.UI.Page.GetCollectionBasedOnMethod(Boolean dontReturnNull) +45
System.Web.UI.Page.DeterminePostBackMode() +65
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +133

2008-05-17 14:26 | clal      

#6楼  回复 引用 查看   

用户上传到一半的时间,刷新页面会造成上传中的文件没有释放
2008-05-18 21:44 | 烟丝      

#7楼[楼主]  回复 引用 查看   

--引用--------------------------------------------------
烟丝: 用户上传到一半的时间,刷新页面会造成上传中的文件没有释放
--------------------------------------------------------

文件会在DataReader类的Dispose方法中释放,但是由于刷新页面时,前面的文件还没来得及释放,后面就开始写文件了,所以会出错,由于组件是用Hidden字段来标识会话的,所以原则上是不能用刷新来重新上传文件的.这里可以改变用Hidden字段来标识会话,也可以在页面限制用户刷新来解决.
2008-05-23 20:50 | 巴山      

#8楼[楼主]  回复 引用 查看   

--引用--------------------------------------------------
contentType.GetField("_completed", flags1).SetValue(httpRawUploadedContent, true);
--------------------------------------------------------
这里仅仅加上这个好还不行的.必须要设置类HttpRawUploadedContent实例的_data和_length属性.不然页面就不能正确获取数据.
2008-05-23 20:53 | 巴山      

#9楼  回复 引用 查看   

大概意思理解,不过代码不会写,坐等源码下载。
2010-12-23 18:06 | 牛腩      

导航

<2008年5月>
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

公告

昵称:巴山
园龄:4年5个月
粉丝:4
关注:0

搜索

 
 

常用链接

我的标签

随笔档案

网络收集的有价值的链接

最新评论

阅读排行榜

评论排行榜

推荐排行榜