安全地复制 NAS 文件服务器上的文件
本文关键字:文件 文件服务器 NAS 复制 安全 | 更新日期: 2024-11-07 10:57:14
我们有一个 NetApp NAS 文件管理器,它似乎不时出现故障,不确定这是否取决于网络问题、负载过重还是文件管理器本身;问题是通常的 System.IO.File.Copy(...)
命令有时会意外失败,因为它在一分钟前工作,一分钟后再次工作......文件管理器正在使用 CIFS 文件系统。
在我的 Log4Net 日志文件中,我看到了异常:
System.IO.IOException:指定的网络名称不再 可用。 at System.IO.__Error.WinIOError(Int32 errorCode, String 也许是全路径)...
网络团队不确定会发生什么以及为什么,我现在在想,如果我可以实现一个简单的尝试/重试系统来复制文件并在发生故障时重试副本,可能是 System.IO.File.Copy 不是为 CIFS 存储设计的,而是为普通的 NTFS 驱动器或稳定的网络存储设计的。
是否有适合执行此复制和重试的常见模式或 .NET 类,或者我应该简单地使用以下伪代码中的方法?
while(!copied && count <5)
{
count++;
try
{
//here copy the file
...
//if no exception copy was ok
copied = true;
}
catch
{
if(count >= 5)
{
// Log that retry limit has been reached...
}
else
{
// make thread to wait for some time,
// waiting time can be in function of count or fixed...
}
}
}
同样的事情也发生在我身上。我有一台旧的 NAS 服务器,Windows 不时显示一个错误,告诉我该驱动器不再可访问。
要管理文件复制过程,也许您可以使用 CopyFileEx(来自 Windows API),如下一个示例所示:
public class SecureFileCopy
{
public static void CopyFile(FileInfo source, FileInfo destination,
CopyFileOptions options, CopyFileCallback callback, object state)
{
if (source == null) throw new ArgumentNullException("source");
if (destination == null)
throw new ArgumentNullException("destination");
if ((options & ~CopyFileOptions.All) != 0)
throw new ArgumentOutOfRangeException("options");
new FileIOPermission(
FileIOPermissionAccess.Read, source.FullName).Demand();
new FileIOPermission(
FileIOPermissionAccess.Write, destination.FullName).Demand();
CopyProgressRoutine cpr = callback == null ?
null : new CopyProgressRoutine(new CopyProgressData(
source, destination, callback, state).CallbackHandler);
bool cancel = false;
if (!CopyFileEx(source.FullName, destination.FullName, cpr,
IntPtr.Zero, ref cancel, (int)options))
{
throw new IOException(new Win32Exception().Message);
}
}
private class CopyProgressData
{
private FileInfo _source = null;
private FileInfo _destination = null;
private CopyFileCallback _callback = null;
private object _state = null;
public CopyProgressData(FileInfo source, FileInfo destination,
CopyFileCallback callback, object state)
{
_source = source;
_destination = destination;
_callback = callback;
_state = state;
}
public int CallbackHandler(
long totalFileSize, long totalBytesTransferred,
long streamSize, long streamBytesTransferred,
int streamNumber, int callbackReason,
IntPtr sourceFile, IntPtr destinationFile, IntPtr data)
{
return (int)_callback(_source, _destination, _state,
totalFileSize, totalBytesTransferred);
}
}
private delegate int CopyProgressRoutine(
long totalFileSize, long TotalBytesTransferred, long streamSize,
long streamBytesTransferred, int streamNumber, int callbackReason,
IntPtr sourceFile, IntPtr destinationFile, IntPtr data);
[SuppressUnmanagedCodeSecurity]
[DllImport("Kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
private static extern bool CopyFileEx(
string lpExistingFileName, string lpNewFileName,
CopyProgressRoutine lpProgressRoutine,
IntPtr lpData, ref bool pbCancel, int dwCopyFlags);
}
public delegate CopyFileCallbackAction CopyFileCallback(
FileInfo source, FileInfo destination, object state,
long totalFileSize, long totalBytesTransferred);
public enum CopyFileCallbackAction
{
Continue = 0,
Cancel = 1,
Stop = 2,
Quiet = 3
}
[Flags]
public enum CopyFileOptions
{
None = 0x0,
FailIfDestinationExists = 0x1,
Restartable = 0x2,
AllowDecryptedDestination = 0x8,
All = FailIfDestinationExists | Restartable | AllowDecryptedDestination
}
MSDN 杂志中有更广泛的描述。
经过数周的研究、测试和痛苦,我似乎终于找到了一个可行的解决方案,决定用调用 Win Server 2008 R2 中可用的 Robocopy 命令来替换System.IO.File.Copy
方法Microsoft该命令似乎从第一次尝试开始就运行良好。这让我感到很舒服,因为我不是在重新发明轮子,而是使用专为我的需求而设计的经过测试的技术。无论如何,感谢大家的回答和评论。