Asp.NET大文件上传组件开发总结(三)---处理文件内容
这一篇相对就要简单一些了,只需要确定对文件的处理思路和与Asp.NET页面信息的传递的问题。
.NET1.1中,Asp.NET将获取的请求内容放入到一个Byte[]类型中,但在Asp.NET2.0中,却将数据封装到一个类型为System.Web.HttpRawUploadedContent的对象中,在这个新对象中,有一个重要的属性:_file,这个属性的类型为TempFile。正好是这个类型提供了将请求内容保存到临时文件的功能。这些信息都可能通过Reflector工具反编译获得(所以啊,做.NET开发,这个工具是必备的)。
在HttpRequest类中,我们可以发现如下用于分析页面各控件值的代码:
类UploadContext用于封装文件信息。
类UploadContextFactory用于会话标志的管理。
在上传页面里,组件将在页面中注册一个名为UploadID的Hidden字段。存放一个GUID作为会话标识。这个标志会在文件上传时,出现在请求内容中,组件通过获取这个会话标志和文件内容,正确将文件保存到临时目录中,并将提取文件信息供页面使用。页面则根据Request["UploadID"]字段在类UploadContextFactory提取上传文件对应的会话标志,并获取文件信息。这样就实现了页面对文件内容的提取。
这样,要求在上传页面的Page_Load事件中,采用如下语句来初始化一个会话,并指定存放文件的目录。
在需要获取文件信息的地方:采用如果语句来获取:
当然这里就存在一个问题是:会话标志过期及没有初始化标志上传文件时的处理(如不请求页面,而直接发送文件,这可能会在用户使用其它工具发送时出现)。这个问题暂时没有处理。
现在,上传的文件可以上传到服务器了,页面也可以获取上传的文件内容以作进一步处理,如限制文件类型、存放到数据库等。
感觉思路有点乱了,那就先写出来,我随后再来整理。
.NET1.1中,Asp.NET将获取的请求内容放入到一个Byte[]类型中,但在Asp.NET2.0中,却将数据封装到一个类型为System.Web.HttpRawUploadedContent的对象中,在这个新对象中,有一个重要的属性:_file,这个属性的类型为TempFile。正好是这个类型提供了将请求内容保存到临时文件的功能。这些信息都可能通过Reflector工具反编译获得(所以啊,做.NET开发,这个工具是必备的)。
在HttpRequest类中,我们可以发现如下用于分析页面各控件值的代码:
private MultipartContentElement[] GetMultipartContent()
{
if (this._multipartContentElements == null)
{
byte[] multipartBoundary = this.GetMultipartBoundary();
if (multipartBoundary == null)
{
return new MultipartContentElement[0];
}
HttpRawUploadedContent entireRawContent = this.GetEntireRawContent();
if (entireRawContent == null)
{
return new MultipartContentElement[0];
}
this._multipartContentElements = HttpMultipartContentTemplateParser.Parse(entireRawContent, entireRawContent.Length, multipartBoundary, this.ContentEncoding);
}
return this._multipartContentElements;
}
说了这么多,只是说明了一个问题:通过改变Asp.NET页面对象的属性值来向页面传送是比较麻烦的。所以我采取单件模式的设计思路。具体是,将获取的文件内容写入到磁盘文件;每次上传文件过程中,初始化一个会话标志,页面通过这个会话标志来提取这些文件信息。在系统中,定义了两个类用来处理这项工作: {
if (this._multipartContentElements == null)
{
byte[] multipartBoundary = this.GetMultipartBoundary();
if (multipartBoundary == null)
{
return new MultipartContentElement[0];
}
HttpRawUploadedContent entireRawContent = this.GetEntireRawContent();
if (entireRawContent == null)
{
return new MultipartContentElement[0];
}
this._multipartContentElements = HttpMultipartContentTemplateParser.Parse(entireRawContent, entireRawContent.Length, multipartBoundary, this.ContentEncoding);
}
return this._multipartContentElements;
}
类UploadContext用于封装文件信息。
类UploadContextFactory用于会话标志的管理。
在上传页面里,组件将在页面中注册一个名为UploadID的Hidden字段。存放一个GUID作为会话标识。这个标志会在文件上传时,出现在请求内容中,组件通过获取这个会话标志和文件内容,正确将文件保存到临时目录中,并将提取文件信息供页面使用。页面则根据Request["UploadID"]字段在类UploadContextFactory提取上传文件对应的会话标志,并获取文件信息。这样就实现了页面对文件内容的提取。
这样,要求在上传页面的Page_Load事件中,采用如下语句来初始化一个会话,并指定存放文件的目录。
UploadContext context = UploadContextFactory.InitUploadContext(this, @"c:\myupload\");
在需要获取文件信息的地方:采用如果语句来获取:
UploadContext context = UploadContextFactory.GetUploadContext();
if ((context != null) && (context.Status == uploadStatus.Complete))
{
context.SaveFile(file1.ClientID, Request.MapPath("/myupload/"));
}
if ((context != null) && (context.Status == uploadStatus.Complete))
{
context.SaveFile(file1.ClientID, Request.MapPath("/myupload/"));
}
当然这里就存在一个问题是:会话标志过期及没有初始化标志上传文件时的处理(如不请求页面,而直接发送文件,这可能会在用户使用其它工具发送时出现)。这个问题暂时没有处理。
现在,上传的文件可以上传到服务器了,页面也可以获取上传的文件内容以作进一步处理,如限制文件类型、存放到数据库等。
感觉思路有点乱了,那就先写出来,我随后再来整理。