首页  ·  知识 ·  云计算
ASP.NET访问网络驱动器(映射磁盘)
sqzhuyi  博客园 http://www.cnblogs.com/sqzhuyi/  综合  编辑:DEZAI   图片来源:网络
也许很多朋友在做WEB项目的时候都会碰到这样一个需求: 当用户上传文件时,需要将上传的文件保存到另外一台专门的文件服务
也许很多朋友在做WEB项目的时候都会碰到这样一个需求:
当用户上传文件时,需要将上传的文件保存到另外一台专门的文件服务器。
 
要实现这样一个功能,有两种解决方案:
方案一、在文件服务器上新建一站点,用来接收上传的文件,然后保存。
方案二、将文件服务器的指定目录共享给WEB服务器,用来保存文件。
 
方案一不用多说,应该是很简单的了,将上传文件的FORM表单的ACTION属性指向文件服务器上的站点即可,我们来重点说下方案二。
 
也许你会说,其实方案二也很简单,在WEB服务器上做下磁盘映射,然后直接访问不就行了。其实不是这样的,IIS默认账户为NETWORK_SERVICE,该账户是没权限访问共享目录的,所以当你把站点部署到IIS上的时候,再访问映射磁盘就会报“找不到路径”的错误。所以,直接创建磁盘映射是行不通的,我们需要在程序中用指定账户创建映射,并用该账户运行IIS进程,下面来说下详细步骤及相关代码。
 
1、在文件服务器上创建共享目录,并新建访问账户。
比如共享目录为:\\192.168.0.9\share
访问账户为:user-1 密码为:123456
 
2、在WEB服务器上新建用户:user-1 密码为:123456,用户组选择默认的user组即可。
 
3、在WEB项目中新建公共类WNetHelper
view sourceprint?
01 using System.Runtime.InteropServices; 
02   
03 public class WNetHelper 
04 { 
05     [DllImport("mpr.dll", EntryPoint = "WNetAddConnection2")] 
06     private static extern uint WNetAddConnection2(NetResource lpNetResource, string lpPassword, string lpUsername, uint dwFlags); 
07   
08     [DllImport("Mpr.dll", EntryPoint = "WNetCancelConnection2")] 
09     private static extern uint WNetCancelConnection2(string lpName, uint dwFlags, bool fForce); 
10   
11     [StructLayout(LayoutKind.Sequential)] 
12     public class NetResource 
13     { 
14         public int dwScope; 
15   
16         public int dwType; 
17   
18         public int dwDisplayType; 
19   
20         public int dwUsage; 
21   
22         public string lpLocalName; 
23   
24         public string lpRemoteName; 
25   
26         public string lpComment; 
27   
28         public string lpProvider; 
29     } 
30   
31     /// <summary> 
32     /// 为网络共享做本地映射 
33    /// </summary> 
34     /// <param name="username">访问用户名(windows系统需要加计算机名,如:comp-1\user-1)</param> 
35     /// <param name="password">访问用户密码</param> 
36     /// <param name="remoteName">网络共享路径(如:\\192.168.0.9\share)</param> 
37     /// <param name="localName">本地映射盘符</param> 
38     /// <returns></returns> 
39     public static uint WNetAddConnection(string username, string password, string remoteName, string localName) 
40     { 
41         NetResource netResource = new NetResource(); 
42   
43         netResource.dwScope = 2; 
44         netResource.dwType = 1; 
45         netResource.dwDisplayType = 3; 
46         netResource.dwUsage = 1; 
47         netResource.lpLocalName = localName; 
48         netResource.lpRemoteName = remoteName.TrimEnd('\\'); 
49         uint result = WNetAddConnection2(netResource, password, username, 0); 
50   
51         return result; 
52     } 
53   
54     public static uint WNetCancelConnection(string name, uint flags, bool force) 
55     { 
56         uint nret = WNetCancelConnection2(name, flags, force); 
57   
58         return nret; 
59     } 
60 }
 
4、为IIS指定运行账户user-1
要实现此功能,有两种办法:
a) 在web.config文件中的<system.web>节点下,添加如下配置:<identity impersonate="true" userName="user-1" password="123456" />
b) 在WEB项目中添加公用类LogonImpersonate
view sourceprint?
01 public class LogonImpersonate : IDisposable 
02 { 
03     static public string DefaultDomain 
04     { 
05         get
06         { 
07             return "."; 
08         } 
09     } 
10   
11     const int LOGON32_LOGON_INTERACTIVE = 2; 
12     const int LOGON32_PROVIDER_DEFAULT = 0; 
13   
14     [System.Runtime.InteropServices.DllImport("Kernel32.dll")] 
15     extern static int FormatMessage(int flag, ref   IntPtr source, int msgid, int langid, ref   string buf, int size, ref   IntPtr args); 
16   
17     [System.Runtime.InteropServices.DllImport("Kernel32.dll")] 
18     extern static bool CloseHandle(IntPtr handle); 
19   
20     [System.Runtime.InteropServices.DllImport("Advapi32.dll", SetLastError = true)] 
21     extern static bool LogonUser( 
22     string lpszUsername, 
23     string lpszDomain, 
24     string lpszPassword, 
25     int dwLogonType, 
26     int dwLogonProvider, 
27     ref   IntPtr phToken 
28     ); 
29   
30     IntPtr token; 
31     System.Security.Principal.WindowsImpersonationContext context; 
32   
33     public LogonImpersonate(string username, string password) 
34     { 
35         if (username.IndexOf("\\") == -1) 
36         { 
37             Init(username, password, DefaultDomain); 
38         } 
39         else
40         { 
41             string[] pair = username.Split(new char[] { '\\' }, 2); 
42             Init(pair[1], password, pair[0]); 
43         } 
44     } 
45     public LogonImpersonate(string username, string password, string domain) 
46     { 
47         Init(username, password, domain); 
48     } 
49     void Init(string username, string password, string domain) 
50     { 
51         if (LogonUser(username, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref   token)) 
52         { 
53             bool error = true; 
54             try
55             { 
56                 context = System.Security.Principal.WindowsIdentity.Impersonate(token); 
57                 error = false; 
58             } 
59             finally
60             { 
61                 if (error) 
62                     CloseHandle(token); 
63             } 
64         } 
65         else
66         { 
67             int err = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); 
68   
69             IntPtr tempptr = IntPtr.Zero; 
70             string msg = null; 
71   
72             FormatMessage(0x1300, ref   tempptr, err, 0, ref   msg, 255, ref   tempptr); 
73   
74             throw (new Exception(msg)); 
75         } 
76     } 
77     ~LogonImpersonate() 
78     { 
79         Dispose(); 
80     } 
81     public void Dispose() 
82     { 
83         if (context != null) 
84         { 
85             try
86             { 
87                 context.Undo(); 
88             } 
89             finally
90             { 
91                 CloseHandle(token); 
92                 context = null; 
93             } 
94         } 
95     } 
96 }
在访问映射磁盘之前首先调用此类为IIS更换运行用户:LogonImpersonate imper = new LogonImpersonate("user-1", "123456");
 
5、在访问共享目录前,调用WNetHelper.WNetAddConnection,添加磁盘映射
view sourceprint?
01 public static bool CreateDirectory(string path) 
02 { 
03     uint state = 0; 
04     if (!Directory.Exists("Z:")) 
05     { 
06         state = WNetHelper.WNetAddConnection(@"comp-1\user-1", "123456", @"\\192.168.0.9\share", "Z:"); 
07     } 
08     if (state.Equals(0)) 
09     { 
10         Directory.CreateDirectory(path); 
11         return true; 
12     } 
13     else
14     { 
15         throw new Exception("添加网络驱动器错误,错误号:" + state.ToString()); 
16     } 
17 }
 
6、完成。
 
简洁代码就是:
LogonImpersonate imper = new LogonImpersonate("user-1", "123456");
WNetHelper.WNetAddConnection(@"comp-1\user-1", "123456", @"\\192.168.0.9\share", "Z:");
Directory.CreateDirectory(@"Z:\newfolder");
file1.SaveAs(@"Z:\newfolder\test.jpg");
 
本文作者:sqzhuyi 来源:博客园 http://www.cnblogs.com/sqzhuyi/
CIO之家 www.ciozj.com 微信公众号:imciow
   
免责声明:本站转载此文章旨在分享信息,不代表对其内容的完全认同。文章来源已尽可能注明,若涉及版权问题,请及时与我们联系,我们将积极配合处理。同时,我们无法对文章内容的真实性、准确性及完整性进行完全保证,对于因文章内容而产生的任何后果,本账号不承担法律责任。转载仅出于传播目的,读者应自行对内容进行核实与判断。请谨慎参考文章信息,一切责任由读者自行承担。
延伸阅读