Файл.Существует, возвращающий false из общего сетевого ресурса
-
03-07-2019 - |
Вопрос
Я работал над проектом ASP.NET, который будет сохранять загруженные файлы в общий сетевой ресурс.Я подумал, что могу просто использовать виртуальный каталог и все будет в порядке, но у меня возникли проблемы с разрешениями для каталога.CreateDirectory.
Я смог загрузить файлы, поэтому решил изменить свой код, чтобы поместить все в один каталог, однако для этого мне нужно использовать File .Существует, чтобы избежать перезаписи дубликатов.
Теперь, когда я обновил весь свой код, я обнаружил, что независимо от того, что я делаю, File.Exists всегда возвращает false (файл определенно существует) при тестировании с общим сетевым ресурсом.
Есть какие-нибудь идеи?Я подхожу к самому концу своей карьеры с сетевыми ресурсами.
Решение
Я совсем недавно работал над очень похожим проектом, где я сохраняю файлы в общий сетевой ресурс.Эти два компьютера находятся в одной подсети, но не управляются контроллером домена, поэтому у каждого компьютера есть свои пользователи.
Я создал пользователя с одинаковым именем пользователя и паролем на обоих компьютерах.Затем я создал общий сетевой ресурс и установил права доступа к папке / общему ресурсу, чтобы разрешить пользователю чтение и запись.
Затем я создал следующий класс для управления олицетворением:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Security.Permissions;
using System.Text;
namespace MyProject.Business.Web
{
public class SecurityManager
{
#region DLL Imports
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);
#endregion
public string Domain { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
private WindowsImpersonationContext m_CurrentImpersonationContext;
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public void StartImpersonation()
{
const int LOGON32_PROVIDER_DEFAULT = 0;
const int LOGON32_LOGON_INTERACTIVE = 2;
IntPtr tokenHandle = IntPtr.Zero;
IntPtr dupeTokenHandle = IntPtr.Zero;
// obtain a handle to an access token
bool wasLogonSuccessful = LogonUser(UserName, Domain, Password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref tokenHandle);
if (!wasLogonSuccessful)
throw new Exception(String.Format("Logon failed with error number {0}", Marshal.GetLastWin32Error()));
// use the token handle to impersonate the user
WindowsIdentity newId = new WindowsIdentity(tokenHandle);
m_CurrentImpersonationContext = newId.Impersonate();
// free the tokens
if (tokenHandle != IntPtr.Zero)
CloseHandle(tokenHandle);
}
public void EndImpersonation()
{
m_CurrentImpersonationContext.Undo();
}
}
}
Затем на странице ASP.NET Я сделал следующее:
SecurityManager sm = new SecurityManager();
sm.UserName = ConfigurationManager.AppSettings["UserFileShareUsername"];
sm.Password = ConfigurationManager.AppSettings["UserFileSharePassword"];
sm.StartImpersonation();
if (!Directory.Exists(folderPath)) Directory.CreateDirectory(folderPath);
File.Move(sourcePath, destinationPath);
sm.EndImpersonation();
Другие советы
File.Exist на самом деле не проверяет наличие файла.Вместо этого он проверяет наличие файлов, к которым у вас есть некоторый доступ.Если вы знаете, что файл существует, скорее всего, проблема в том, что у вас нет к нему доступа.
Возможно, ваш код, который запущен (т. е.ASP.NET серверный код) выполняется от имени пользователя (например,пользователь IIS), у которого нет прав доступа к этому сетевому ресурсу.
Я думаю, что IIS не должен запускаться как пользователь с высокими привилегиями, который по умолчанию имеет разрешение на просмотр общих ресурсов на других компьютерах.
Я использовал почти тот же код, но мой класс реализовал интерфейс IDisposable и добавил функцию Undo() к методу Dispose().Этот код работает нормально, если вы единственный разработчик, использующий его, и вы всегда будете делать все правильно, не так ли?