[转载]ASP.NET访问网络驱动器(映射磁盘) – 路人乙 – 博客园.
也许很多朋友在做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
01 |
using System.Runtime.InteropServices; |
03 |
public class WNetHelper |
05 |
[DllImport( "mpr.dll" , EntryPoint = "WNetAddConnection2" )] |
06 |
private static extern uint WNetAddConnection2(NetResource lpNetResource, string lpPassword, string lpUsername, uint dwFlags); |
08 |
[DllImport( "Mpr.dll" , EntryPoint = "WNetCancelConnection2" )] |
09 |
private static extern uint WNetCancelConnection2( string lpName, uint dwFlags, bool fForce); |
11 |
[StructLayout(LayoutKind.Sequential)] |
12 |
public class NetResource |
18 |
public int dwDisplayType; |
22 |
public string lpLocalName; |
24 |
public string lpRemoteName; |
26 |
public string lpComment; |
28 |
public string lpProvider; |
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) |
41 |
NetResource netResource = new NetResource(); |
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); |
54 |
public static uint WNetCancelConnection( string name, uint flags, bool force) |
56 |
uint nret = WNetCancelConnection2(name, flags, force); |
4、为IIS指定运行账户user-1
要实现此功能,有两种办法:
a) 在web.config文件中的<system.web>节点下,添加如下配置:<identity impersonate=”true” userName=”user-1″ password=”123456″ />
b) 在WEB项目中添加公用类LogonImpersonate
01 |
public class LogonImpersonate : IDisposable |
03 |
static public string DefaultDomain |
11 |
const int LOGON32_LOGON_INTERACTIVE = 2; |
12 |
const int LOGON32_PROVIDER_DEFAULT = 0; |
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); |
17 |
[System.Runtime.InteropServices.DllImport( "Kernel32.dll" )] |
18 |
extern static bool CloseHandle(IntPtr handle); |
20 |
[System.Runtime.InteropServices.DllImport( "Advapi32.dll" , SetLastError = true )] |
21 |
extern static bool LogonUser( |
31 |
System.Security.Principal.WindowsImpersonationContext context; |
33 |
public LogonImpersonate( string username, string password) |
35 |
if (username.IndexOf( "\\" ) == -1) |
37 |
Init(username, password, DefaultDomain); |
41 |
string [] pair = username.Split( new char [] { '\\' }, 2); |
42 |
Init(pair[1], password, pair[0]); |
45 |
public LogonImpersonate( string username, string password, string domain) |
47 |
Init(username, password, domain); |
49 |
void Init( string username, string password, string domain) |
51 |
if (LogonUser(username, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token)) |
56 |
context = System.Security.Principal.WindowsIdentity.Impersonate(token); |
67 |
int err = System.Runtime.InteropServices.Marshal.GetLastWin32Error(); |
69 |
IntPtr tempptr = IntPtr.Zero; |
72 |
FormatMessage(0x1300, ref tempptr, err, 0, ref msg, 255, ref tempptr); |
74 |
throw ( new Exception(msg)); |
在访问映射磁盘之前首先调用此类为IIS更换运行用户:LogonImpersonate imper = new LogonImpersonate(“user-1”, “123456”);
5、在访问共享目录前,调用WNetHelper.WNetAddConnection,添加磁盘映射
01 |
public static bool CreateDirectory( string path) |
04 |
if (!Directory.Exists( "Z:" )) |
06 |
state = WNetHelper.WNetAddConnection( @"comp-1\user-1" , "123456" , @"\\192.168.0.9\share" , "Z:" ); |
10 |
Directory.CreateDirectory(path); |
15 |
throw new Exception( "添加网络驱动器错误,错误号:" + state.ToString()); |
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”);
有不明白的可以发EMAIL给我:sqzhuyi@gmail.com