很多人把NET写好的上传功能本地跑得好好的,一放到服务器IIS上就各种闹脾气,文件死活传不上去。这个事儿太常见了,我也踩过不少坑,今天就把那些最容易出问题的点儿挨个捋一遍,你照着排查,基本都能解决。
先看权限,这是头号嫌疑人。本地开发的时候你用管理员身份跑VS,当然啥都能干,但IIS里的应用程序池跑的是独立账号,默认叫IIS_IUSRS或者IUSR,这俩货对磁盘的写入权限非常有限。你的上传目录要是没给这个账号开写权限,那必然是传一个失败一个。右键你放上传文件的文件夹,选属性,切到安全页签,点编辑,添加IIS_IUSRS用户,给完全控制或者至少给修改和写入权限。注意别只给网站根目录,上传目录一般是独立文件夹,比如Uploads或者Files这种,记得单独把这文件夹的权限也加上。
再有一个特别容易忽略的坑是应用程序池的32位设置。现在服务器大多是64位的,IIS默认应用程序池禁止运行32位程序,要是你网站打包的时候引用了某些32位的组件,或者代码里调用了32位的Excel、Word操作库,那个上传处理程序在加载这些库的时候就直接崩了,表现出来就是上传进度条走完但报错,或者干脆就没反应。解决办法是在IIS的应用程序池里,找到你那网站对应的池,右键高级设置,把启用32位应用程序改成True,然后把池回收一下。
配置文件也别放过。web.config里如果设置了maxRequestLength限制,默认只有4MB,超过这个大小的文件传上去必然被拒,页面直接报错说请求长度超过了限制。常见做法是把maxRequestLength调大,比如52428800也就是50MB,同时把executionTimeout也调长一点,默认110秒对网速慢的大文件来说根本不够用。还要注意httpRuntime里有个targetFramework配置,要是和服务器IIS上装的.NET版本对不上,也会出幺蛾子。
还有种情况是你代码里用了相对路径写文件,比如Server.MapPath来定位物理路径,本地没问题,但IIS上的站点路径如果和你在IIS里配置的虚拟目录对不上,MapPath返回的路径可能指向一个不存在的目录,然后程序就抛出DirectoryNotFoundException或者类似异常。这个可以用绝对路径写在日志里,先看看实际写到哪儿去了,再调整代码或者IIS里的虚拟目录映射。

别忘了IIS的请求筛选功能。IIS7以上版本自带了一个Request Filtering,它默认对文件扩展名和请求大小也有一定限制,有时你web.config放开了但IIS这层又卡住了拦了一道。你去IIS管理器里选中你的站点,双击请求筛选,看配置编辑功能里有没有限制请求内容的长度,默认允许的最大内容长度可能是30000000字节,也就是30MB左右,你要是传更大的文件就得把这里也调大。
防火墙和杀毒软件也不能完全忽略,服务器上安全软件对临时目录的实时监控偶尔会锁住上传过程中写入临时文件的操作,导致刷新页面后文件消失或报IO错误。临时清理一下杀毒软件的拦截日志,或者把上传目录加入白名单,很多时候能解决一些莫名其妙的问题。
最后说个数据:根据微软官方文档和很多部署案例,IIS上传失败的求助里,大约七成都是权限问题,两成是配置限制,剩下的才是代码或环境兼容。所以你按这个优先级排查,最省时间。把应用池回收一下再试,有时候改了配置不生效是池子还挂着旧进程,这个操作五分钟搞定,却经常能救急。
上传这块要是能配个日志记录,每次写入文件前把操作人、文件大小、目标路径、异常消息都记下来,排查起来会轻松十倍。不然全靠猜那真的很折腾。但绝大多数情况下,把IIS_IUSRS权限给全、应用程序池32位打开、web.config大小限制调高这三板斧砍下去,基本都能稳了。拿不准的时候再去事件查看器看看报错信息,Windows日志里那个应用程序日志通常能给出更具体的异常堆栈,一条条比对着来解决就行。