多文件批量上传

用一个页面实现文件上传,一般只需要使用HtmlInputFile的runat=server版本就行了,但是现在有些不同的地方:
1、直接上传到数据库的image类型的字段中,而不产生本地文件;
2、多个文件同时上传;
3、上传的文件组最后要同其他相关信息进行关联;

解决方法主要有两种:
1、每次上传一个文件到临时目录,返回并保存相关信息到ViewState,最后提交的时候,统一将文件写入数据库,并根据相关信息做关联;
2、每次上传一个文件到数据库,返回并保存相关信息到ViewState,最后提交的时候,根据相关信息做关联;
3、每次采集HtmlInputFile中的信息到ListBox,最后统一上传多个文件,并做相关关联;

无疑,第三种是其中最好的一种,但是上传多个文件却比较麻烦,本来想在提交的时候,分别多次设置 HtmlInputFile.PostedFile.FileName属性,再多次调用SaveAs进行上传,但在一次提交过程中它不允许重设 FileName属性(事后想想,确实应该不行:P)
后来又想在后台动态添加HtmlInputFile控件并且设其Visible属性为false,结果好像还是不行,因为还是不准自己指定那个怨念的FileName属性

结果:
增加文件按钮:
if( null == m_htmlInputFile )
m_htmlInputFile = new ArrayList();
m_htmlInputFile.Add( FileInputField );

其中FileInputField为System.Web.UI.HtmlControls.HtmlInputFile类型;
并且注意设置m_htmlInputFile这个ArrayList为static,以防每次增加文件后被刷新为null:(
这里其实就每次Add那个Html控件就行了,他们都对应相同的html控件,但是后台的对象每Add一次增加一个:)

提交按钮:
if( null == m_imageList )
m_imageList = new ArrayList();
if( null == m_imageTypeList )
m_imageTypeList = new ArrayList();
foreach( HtmlInputFile hif in m_htmlInputFile )
{
System.Drawing.Image image = System.Drawing.Image.FromStream( hif.PostedFile.InputStream );
m_imageList.Add( image );
m_imageTypeList.Add( hif.PostedFile.ContentType );
}

显示图片:
在GetImage.aspx?ImageID=*页面的Page_Load中
Response.ContentType = m_image.ImageType;
Response.BinaryWrite( m_image.Img );

注意采用BinaryWrite以及设置ContentType为image/pjpeg等

最后在保存文件到后端数据库的时候有点小不爽:
MemoryStream ms = new MemoryStream();
image.Save( ms, System.Drawing.Imaging.ImageFormat.Jpeg );//image是System.Drawing.Image
m_image = new byte[ms.Length];//m_image是byte[]
ms.Position = 0;
//If Too Long, ...
ms.Read( m_image, 0, Convert.ToInt32(ms.Length));

这里ms.Length是long类型,但是同一个类-MemoryStream的Read方法的第三个参数是int型,涉及到一个向下的类型转换,如果Length过大,应该这里会有问题,不知是怎么回事:(

发布Web Services

笔记本上Release后一切正常的Web Services,部署到另外一台2003的服务器上,出现两个问题:

1、Critical Error:

…没有权限访问注册表

其实只是在写入EventLog的时候ASPNET的权限不够,不过奇怪的是把ASPNET和匿名帐户加入Administrator组,重启,好像权限还是不够>.<

查看其列出的跟踪堆栈,发现好像是Enterprise Library中ADO.NET连接数据库的问题,在网上查了查,有用的文章不多,最后居然就在EntLib的FAQ里,发现是没有正确部署EnterLib程序集的问题。

安装程序工具(Installutil.exe)
允许通过执行指定程序集的安装程序组件来安装和卸载服务器资源。
注意: 在“%windir%Microsoft.NETFrameworkv1.1.xxxx”中可以找到Installutil.exe,其中xxxx是您使用的 .NET Framework 的内部版本号。

Installutil Microsoft.Practices.EnterpriseLibrary.Common.dll
Installutil Microsoft.Practices.EnterpriseLibrary.Configuration.dll
Installutil Microsoft.Practices.EnterpriseLibrary.Data.dll

一切恢复正常。

不过还是不知道为什么他的程序集部署的时候必须Install,而自己的dll就不用这一步。

PS:
删除用
Installutil /u xxx.dll

2、localhost访问没有问题,但用www.xxx.com访问,出错

在 .NET Framework 1.1 远程环境中,默认情况下 HTTP GET 和 HTTP POST 同时被禁用。这是出于安全方面的考虑。
当 Web 服务升级到 .NET Framework 1.1 后,应用程序使用 HTTP GET 或 HTTP POST 调用 Web 服务时会失败。
这些应用程序会收到以下一条错误信息 System.Net.WebException指出无法识别请求格式。

由于使用POST,现在已基本不可能转成SOAP协议,只有将其打开,更改Web.Config文件:
<configuration>
<system.web>
<webServices>
<protocols>
<!--
<add name="HttpGet">
-->
<add name="HttpPost"/>
</protocols>
</webServices>
</system.web>
</configuration>

Bug in Enterprise Library

TNND,最近在用Enterprise Library的时候,需要自己实现他的IAuthorizationProvider接口,然后在用他的配置工具(EntLibConfig.exe)进行配置的时候,老是提示:

The type name XXX is not valid.

但是我看了几百遍,还是觉得应该实现方式没有什么问题。好在Enterprise Library带有源码,我直接把他配置工具的下面行注释掉:

// errors.Add(instance, name, SR.ExceptionTypeNotValid(typeName));

于是一切使用正常,说明确实没有问题。但心中总是不爽。

今天在网上翻,终于发现,果然是微软的一个bug….

The problem is that some of the configuration settings have the [TypeValidation] attribute, which will attempt to check that the assembly qualified name of the type is a valid type. Unfortunately, this is running in an App Domain which is rooted in the EntLibConfig.exe directory, and so will only be able to resolves types in assemblies in that directory, or in the GAC.

而且提供的暂时解决方案居然就是直接注释掉那一行,他还友情提醒,因为没有检测,自己注意类型不要弄错了- –

唉…郁闷- –

所以,如果确实不想改动源码,可以直接把生成的DLL,用生成后事件copy到EntLibConfig.exe目录下就行了。

公车奇遇

那天晚上依然很晚下班,等了半天,倒霉685才来,已经人满为患了,我就站在中间位置。

旁边单座上坐着一个身材魁梧,肉顿顿的男子,约25岁。一个娇小女子坐在男子腿上,二人呈环抱状,两个人不停的谈话,男子嗓门极大,然后他说:”我给你猜个谜吧””好呀好呀””说巧克力和爆米花打架,巧克力赢了,打一种食物”,那女的做痴呆思考状,然后我也在那想,我估计车上很多人都在思考,后来那女的猜了几个不着边的东西都不对,我也快到站了,我就着急呀,快说答案呀,要不我得别扭死…

那男的很深沉的说,”我可说答案了呀…答案就是,巧克力棒!!!哈哈哈哈哈”…

我差点一口血吐出来,然后整个车上弥漫着那雄壮男的笑声。