c# - 在 NAS 文件管理器上安全地复制文件

标签 c# .net nas cifs

我们有一个 NetApp NAS 文件管理器,它似乎有时会失败,不确定这是否取决于网络问题、重负载或文件管理器本身;问题是通常的 System.IO.File.Copy(...) 命令有时会意外失败,而它在一分钟前工作并在一分钟后再次工作......文件管理器正在使用 CIFS文件系统。

在我的 Log4Net 日志文件中我看到异常:

System.IO.IOException: The specified network name is no longer available. at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) ...

网络团队不确定会发生什么以及为什么,我现在正在考虑是否可以实现一个简单的尝试/重试系统来复制文件并在失败的情况下重试复制,它可能是 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 Server并且不时Windows shows an error telling me that the drive is not accessible anymore .
管理file copy process也许你可以改用 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
}

有一个 more extensive description in MSDN Magazine .

关于c# - 在 NAS 文件管理器上安全地复制文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11871737/

相关文章:

c# - 在 .NET MVC 中使用 LDAP/网络凭据验证用户

.net - AForge.Video.FFMPEG.dll 中发生 AccessViolationException

linux - 连接 Windows 至 NAS - Samba 服务器

nas - 如何使用 API 访问 Synology NAS 硬盘

c# - 将图像和超链接控件添加到面板

c# - ASP.NET Web 用户控件库

c# - 在 C# 中, '|=' 是做什么的?

c# - 为什么将国际化 "words"存储在单独的 (xml) 文件中?

c# - 嵌套 if ... else 流的更简单/更有效的方法?

python - 使用python登录NAS