得,今天就来唠唠这个。我刚开始接触网页开发那会儿,经常需要搞点文件上传下载,或者读取服务器上某个文件夹里的配置文件啥的。一开始真是一头雾水,不知道代码里怎么才能拿到服务器上那个文件的真实存放地址。
你想,咱们在浏览器里访问的是一个网址,比如 `/upload/images/*` 这种。但这个文件在服务器硬盘上,可能放在 `D:\wwwroot\mywebapp\upload\images\*` 这样的地方。代码跑在服务器上,它需要知道的是后面这个硬盘路径,才能去操作文件嘛
后来翻资料,加上问问旁边座的老哥,知道有这么个东西。当时感觉,这不就解决嘛试一下,确实挺好使。比如在我的网页后台代码(就是那个 .* 文件)里,想拿到 `images` 文件夹在服务器上的完整路径,就直接写:
string shiJiLuJing = *("/upload/images/");
这样一来,shiJiLuJing
这个变量里存的就是类似 `D:\wwwroot\mywebapp\upload\images\` 这样的字符串。用起来感觉真方便,当时觉得这玩意儿就是万能钥匙。
但是,后来就遇到坑
有一次,我把一些文件处理的逻辑,想封装到一个单独的类文件里去,就是那种不是网页后台代码,而是专门处理业务逻辑的 `.cs` 文件。想着这样代码结构清晰点,以后也好维护。然后我就很自然地,想在那个类的方法里面,也用 来获取路径。
结果你猜怎么着?直接报错! 编译器告诉我,Server
这个东西在这里不认识。我当时就懵,咋回事?明明在网页后台代码里用得好好的,挪到另一个类里就不行?
搞半天,查些资料才明白。原来这个 Server
对象,还有它下面的 MapPath
方法,是跟当前的网页请求上下文绑在一起的。简单说,就是只有在处理一个具体的网页访问请求时(比如在 `.aspx` 页面或它的后台代码里),这个 Server
才天然存在,才能直接用。
我那个单独的类文件,它本身不处理网页请求,就是个普通的类,自然也就没有这个默认的 Server
对象让你用。
那咋办?
后来发现有几种办法可以绕过去:
- 传参数: 在调用那个类的方法时,把在网页后台代码里获取到的 的结果(也就是那个物理路径字符串)当做参数传进去。这样类里面就直接用这个路径字符串,不用自己去调用
MapPath
。 - 传HttpContext: 把当前的网页请求上下文对象()传到那个类的方法里,然后通过
*.MapPath
来调用。这个有点麻烦,感觉耦合有点重。 - 用别的方法: 后来发现还有一个叫 的东西。这个好像更通用一些,不那么依赖于当前的网页请求。在我的那个类文件里用这个,也能拿到想要的服务器物理路径,而且似乎更推荐在非页面后台代码的场景下使用。
我基本上就倾向于用 ,或者干脆就在靠近网页处理的地方把路径算然后把算好的路径传给后面的业务逻辑类。这样一来,代码也清楚,也不容易出那种“这里不能用”的怪问题。
所以说,这个 是个好东西,特别是在处理跟当前访问的网页相关的路径时很直接。但它不是在哪都能直接用的,得分清楚场合。搞明白它依赖才能用得顺手,不然就得像我一样,踩坑才知道回头。