也许很多朋友在做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

  1. using System.Runtime.InteropServices;
  2. public class WNetHelper
  3. {
  4. [DllImport("mpr.dll", EntryPoint = "WNetAddConnection2")]
  5. private static extern uint WNetAddConnection2(NetResource lpNetResource, string lpPassword, string lpUsername, uint dwFlags);
  6. [DllImport("Mpr.dll", EntryPoint = "WNetCancelConnection2")]
  7. private static extern uint WNetCancelConnection2(string lpName, uint dwFlags, bool fForce);
  8. [StructLayout(LayoutKind.Sequential)]
  9. public class NetResource
  10. {
  11. public int dwScope;
  12. public int dwType;
  13. public int dwDisplayType;
  14. public int dwUsage;
  15. public string lpLocalName;
  16. public string lpRemoteName;
  17. public string lpComment;
  18. public string lpProvider;
  19. }
  20. /// <summary>
  21. /// 为网络共享做本地映射
  22. /// </summary>
  23. /// <param name="username">访问用户名(windows系统需要加计算机名,如:comp-1\user-1)</param>
  24. /// <param name="password">访问用户密码</param>
  25. /// <param name="remoteName">网络共享路径(如:\\192.168.0.9\share)</param>
  26. /// <param name="localName">本地映射盘符</param>
  27. /// <returns></returns>
  28. public static uint WNetAddConnection(string username, string password, string remoteName, string localName)
  29. {
  30. NetResource netResource = new NetResource();
  31. netResource.dwScope = 2;
  32. netResource.dwType = 1;
  33. netResource.dwDisplayType = 3;
  34. netResource.dwUsage = 1;
  35. netResource.lpLocalName = localName;
  36. netResource.lpRemoteName = remoteName.TrimEnd('\\');
  37. uint result = WNetAddConnection2(netResource, password, username, 0);
  38. return result;
  39. }
  40. public static uint WNetCancelConnection(string name, uint flags, bool force)
  41. {
  42. uint nret = WNetCancelConnection2(name, flags, force);
  43. return nret;
  44. }
  45. }

4、为IIS指定运行账户user-1

要实现此功能,有两种办法:

a) 在web.config文件中的<system.web>节点下,添加如下配置:<identity impersonate="true" userName="user-1" password="123456" />

b) 在WEB项目中添加公用类LogonImpersonate

  1. public class LogonImpersonate : IDisposable
  2. {
  3. static public string DefaultDomain
  4. {
  5. get
  6. {
  7. return ".";
  8. }
  9. }
  10. const int LOGON32_LOGON_INTERACTIVE = 2;
  11. const int LOGON32_PROVIDER_DEFAULT = 0;
  12. [System.Runtime.InteropServices.DllImport("Kernel32.dll")]
  13. extern static int FormatMessage(int flag, ref   IntPtr source, int msgid, int langid, ref   string buf, int size, ref   IntPtr args);
  14. [System.Runtime.InteropServices.DllImport("Kernel32.dll")]
  15. extern static bool CloseHandle(IntPtr handle);
  16. [System.Runtime.InteropServices.DllImport("Advapi32.dll", SetLastError = true)]
  17. extern static bool LogonUser(
  18. string lpszUsername,
  19. string lpszDomain,
  20. string lpszPassword,
  21. int dwLogonType,
  22. int dwLogonProvider,
  23. ref   IntPtr phToken
  24. );
  25. IntPtr token;
  26. System.Security.Principal.WindowsImpersonationContext context;
  27. public LogonImpersonate(string username, string password)
  28. {
  29. if (username.IndexOf("\\") == -1)
  30. {
  31. Init(username, password, DefaultDomain);
  32. }
  33. else
  34. {
  35. string[] pair = username.Split(new char[] { '\\' }, 2);
  36. Init(pair[1], password, pair[0]);
  37. }
  38. }
  39. public LogonImpersonate(string username, string password, string domain)
  40. {
  41. Init(username, password, domain);
  42. }
  43. void Init(string username, string password, string domain)
  44. {
  45. if (LogonUser(username, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref   token))
  46. {
  47. bool error = true;
  48. try
  49. {
  50. context = System.Security.Principal.WindowsIdentity.Impersonate(token);
  51. error = false;
  52. }
  53. finally
  54. {
  55. if (error)
  56. CloseHandle(token);
  57. }
  58. }
  59. else
  60. {
  61. int err = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
  62. IntPtr tempptr = IntPtr.Zero;
  63. string msg = null;
  64. FormatMessage(0x1300, ref   tempptr, err, 0, ref   msg, 255, ref   tempptr);
  65. throw (new Exception(msg));
  66. }
  67. }
  68. ~LogonImpersonate()
  69. {
  70. Dispose();
  71. }
  72. public void Dispose()
  73. {
  74. if (context != null)
  75. {
  76. try
  77. {
  78. context.Undo();
  79. }
  80. finally
  81. {
  82. CloseHandle(token);
  83. context = null;
  84. }
  85. }
  86. }
  87. }

在访问映射磁盘之前首先调用此类为IIS更换运行用户:LogonImpersonate imper = new LogonImpersonate("user-1", "123456");

5、在访问共享目录前,调用WNetHelper.WNetAddConnection,添加磁盘映射

  1. public static bool CreateDirectory(string path)
  2. {
  3. uint state = 0;
  4. if (!Directory.Exists("Z:"))
  5. {
  6. state = WNetHelper.WNetAddConnection(@"comp-1\user-1", "123456", @"\\192.168.0.9\share", "Z:");
  7. }
  8. if (state.Equals(0))
  9. {
  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");

ASP.NET访问网络驱动器(映射磁盘)的更多相关文章

  1. ASP.NET访问网络映射盘&实现文件上传读取功能

    最近在改Web的时候,遇到一个问题,要跨机器访问共享文件夹,以实现文件正常上传下载功能. 要实现该功能,可以采用HTTP的方式,也可以使用网络映射磁盘的方式,今天主要给大家分享一下使用网络映射磁盘的方 ...

  2. VBS映射网络驱动器 映射网络驱动器

    Dim objNetwork Set objNetwork = CreateObject("Wscript.Network") if objNetwork.EnumNetworkD ...

  3. iis访问网络路径映射问题(UNC share)

    最近在做一个功能,涉及到nas网络磁盘文件的保存和访问,在服务器上将对应的路径映射为Z盘,结果在iis上部署网站直接访问该路径,报无法找到该路径的错误. 用的是.net core开发,在vs直接启动程 ...

  4. IIS虚拟目录实现与文件服务器网络驱动器映射共享

    这篇文章转载别人,想原创作者致敬! 我本人也遇到同样的问题,故转载记录. 本文重点描述如何使用IIS访问共享资源来架设站点或执行 ASP.Net 等脚本. 通常情况下,拥有多台服务器的朋友在使用IIS ...

  5. 转:IIS虚拟目录实现与文件服务器网络驱动器映射共享

    这篇文章转载别人,想原创作者致敬! 我本人也遇到同样的问题,故转载记录. 本文重点描述如何使用IIS访问共享资源来架设站点或执行 ASP.Net 等脚本. 通常情况下,拥有多台服务器的朋友在使用IIS ...

  6. IIS下访问网络驱动器(网络位置)

    System.Diagnostics.Process p = new System.Diagnostics.Process(); p.StartInfo.FileName = "cmd.ex ...

  7. asp.net访问网络路径方法(模拟用户登录)

    public class IdentityScope : IDisposable { // obtains user token [DllImport("advapi32.dll" ...

  8. IIS/ASP.NET访问共享文件夹的可用方式

    [截止2014-10-14] 网上搜索了很多篇文章,所提及的总共有两种方式: 1.Asp.Net模拟登陆: 例如: 实战ASP.NET访问共享文件夹(含详细操作步骤) 实现一个2008serve的II ...

  9. 关于windows service不能访问网络共享盘(NetWork Drive)的解决方案

    我映射一个网络驱动器到本机的时候,发现本机的程序直接能访问读取网络驱动器,但是把本机的程序作为本机的windows服务运行的时候就不能访问了. Qt中的QDir::exist(folder)访问失败. ...

随机推荐

  1. PHP学习方向-进阶2(三)

    实践篇 给定二维数组,根据某个字段排序 如何判断上传文件类型,如:仅允许 jpg 上传 不使用临时变量交换两个变量的值 $a=1; $b=2; => $a=2; $b=1; strtoupper ...

  2. HDU 1836 畅通工程

    畅通工程 Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 18636 ...

  3. (39.3) Spring Boot Shiro权限管理【从零开始学Spring Boot】

    在学习此小节之前您可能还需要学习: (39.1) Spring Boot Shiro权限管理[从零开始学Spring Boot] http://412887952-qq-com.iteye.com/b ...

  4. oracle导入少量数据(少于10M)

    工具用PL/SQL Developer select * from temp1 for update;开锁,点+号,直接从Excel复制,然后粘贴. 程序猿必读

  5. 233 Matrix 矩阵快速幂

    In our daily life we often use 233 to express our feelings. Actually, we may say 2333, 23333, or 233 ...

  6. http-runtime属性

    配置httpRuntime也可以让FileUpload上传更大的文件,不过设置太大了会因用户将大量文件传递到该服务器而导致的拒绝服务攻击(属性有说明) 属性 属性 选项 说明 appRequestQu ...

  7. N天学习一个linux命令之rpm

    用途 RPM是Redhat Package Manager三个单词首字母缩写,是类redhat linux系统的包管理器,用它可以安装包(二进制/源码),升级包,删除包,查询包信息等功能.RPM软件包 ...

  8. Clojure:将两个list合并成一个map

    假设我们有两个list,分别是: (def a [“one” “two” “three”]) (def b [1 2 3]) 我们要把它们合为一个键值对应的map,做法很简单: 1. 先将a和b合为一 ...

  9. [Cypress] Create Aliases for DOM Elements in Cypress Tests

    We’ll often need to access the same DOM elements multiple times in one test. Your first instinct mig ...

  10. http get请求获取server返回的应答数据

    libcurl库中的參数CURLOPT_WRITEFUNCTION所设置的回调函数应该是这种: size_t fun_cb( char *ptr, size_t size, size_t nmemb, ...